I just want to write a simple multiclient server with named pipes. I have a problem with server-side. When I had only reading, everything was great. Now, I added a possibility for server to send a message back to client - and now its not working at all ...
Heres my server code (notice, that when I remove commented lines /* */, it reads from all the clients, it works just fine but - READING ONLY). How to force server to write to all the clients too? (The concept is that client first write sends to server clients fifoname. Server creates and opens such fifo and can write to it but the writing part still doesnt want to work ... :/)
int main (int argc, char *argv[])
{
int fd_in, fd_out, j, result;
char buffer[4096];
const char *myfifo = "./fifo";
mkfifo(myfifo, 0666 );
if ((fd_in = open(myfifo, O_RDONLY | O_NONBLOCK)) < 0)
perror(myfifo);
printf("Server reads from: %s\n", myfifo);
for (;;) {
fd_set fds_r;
fd_set master;
FD_ZERO (&fds_r);
FD_ZERO (&master);
FD_SET (fd_in, &fds_r);
master = fds_r;
if ((result = select(fd_in + 1, &fds_r, NULL, NULL, NULL)) < 0)
perror ("select()");
if (! FD_ISSET(fd_in, &fds_r))
continue;
result = read(fd_in, buffer, 4096);
printf("FROM CLIENT: %s\n", buffer);
/*if(startsWith(buffer, "#"))
{
// remove # from message from client
string login = removePrefix(buffer);
string fifoname = "./fifo";
fifoname += login;
printf("REGISTERED: %s\n", fifoname.c_str());
mkfifo(fifoname.c_str(), 0666);
if ((fd_out = open(fifoname.c_str(), O_WRONLY)) < 0)
perror(fifoname.c_str());
FD_SET (fd_out, &master);
}
/* for(j = 0; j <= fd_in; j++) {
// send to everyone!
if (FD_ISSET(j, &master)) {
// except the listener and ourselves
if (j != fd_out) {
if (write(j, buffer, sizeof(buffer)) == -1) {
perror("write");
}
}
}
}*/
memset(buffer, 0, sizeof(buffer));
}
fprintf (stderr, "Got EOF!\n");
close (fd_in);
return 0;
}
client.cpp
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include <string.h>
using namespace std;
int main(int argc, char **argv)
{
int client_to_server;
const char *myfifo = "./fifo";
int server_to_client;
string f = "./fifo";
string u(argv[1]);
f += u;
const char *myfifo2 = f.c_str();
char str[BUFSIZ];
/* write str to the FIFO */
client_to_server = open(myfifo, O_WRONLY);
server_to_client = open(myfifo2, O_RDONLY);
// register message #username
string reg = "#";
reg += u;
printf("Client writes to: %s\n", myfifo);
printf("Client reads from: %s\n", myfifo2);
// first write to server, he can now make a fifo called fifo+username
if(write(client_to_server, reg.c_str(), strlen(reg.c_str())) == -1)
perror("write:");
while(1)
{
printf("Input message to serwer: ");
scanf("%s", str);
if(write(client_to_server, str, sizeof(str))==-1)
perror("Write:"); //Very crude error check
if(read(server_to_client,str,sizeof(str))==-1)
perror("Read:"); // Very crude error check
printf("...received from the server: %s\n",str);
}
close(client_to_server);
close(server_to_client);
/* remove the FIFO */
return 0;
}
My output:
server-side:
$ ./SERVER
Server reads from: ./fifo
FROM CLIENT: #username
FROM CLIENT: hello
FROM CLIENT:
FROM CLIENT: ?
FROM CLIENT:
FROM CLIENT: huh
FROM CLIENT:
client-side:
$ ./CLIENT username
Client writes to: ./fifo
Client reads from: ./fifousername
Input message to serwer: hello
Read:: Bad file descriptor
...received from the server: hello
Input message to serwer: ?
Read:: Bad file descriptor
...received from the server: ?
Input message to serwer: huh
Read:: Bad file descriptor
...received from the server: huh
Input message to serwer: