I want to write a echo client-server app using named pipes (I did it with sockets, it worked, but now I want to do the same with named pipes.) Server has to be multithread.
I thought my programs work when I run them for the first time, it was all good. Every client connected to server got a message from it.
But now, when I tried to run programs for the second time, I still get this message:
mkfifo client2server: File exists
(many such messages). This is my output when I tried to run ./echoserver:
$ ./echoserver
Server is working ...
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
mkfifo client2server: File exists
how to fix it to work as I want it to? To make a real multithread echo server-client app?
Heres my code:
echoserver.cpp
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <sstream>
using namespace std;
string toString(int d)
{
ostringstream ss;
ss << d;
return ss.str();
}
void* clients_service(void * arg)
{
int client_id = *((int*)&arg), server2client = -1, buffsize = 255, bytes_read = -1, client2server = -1;
client_id++;
char buffer[255];
string fifoname = "/tmp/server2client";
fifoname += toString(client_id);
string fifoclient = "/tmp/client2server";
fifoclient += toString(client_id);
if(mkfifo(fifoclient.c_str(), 0666) == -1)
{
perror("mkfifo client2server");
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
if((client2server = open(fifoclient.c_str(), O_RDONLY)) == -1)
{
perror("open client2server");
exit(1);
}
if(mkfifo(fifoname.c_str(), 0666) == -1)
{
perror("mkfifo server2client");
exit(1);
}
if((server2client = open(fifoname.c_str(), O_WRONLY)) == -1)
{
perror("open server2client");
exit(1);
}
for(;;)
{
if ((bytes_read = read(client2server, buffer, buffsize))== -1)
{
perror("read");
exit(1);
}
else if (bytes_read == 0)
{
fprintf(stdout, "Connection closed\n");
break;
}
buffer[bytes_read] = '\0';
if (strcmp("\\q",buffer)==0)
{
fprintf(stdout, "Server OFF.\n");
break;
}
fprintf(stdout, "From client: %s\n", buffer);
if ((write(server2client,buffer, strlen(buffer)))== -1)
{
perror("write");
break;
}
fprintf(stdout, "Send to client: %s\n", buffer);
// clean buffer from any data
memset(buffer, 0, sizeof(buffer));
}
close(client2server);
close(server2client);
unlink(fifoname.c_str());
unlink(fifoclient.c_str());
}
int main(int argc, char **argv)
{
int clientsCounter = 0;
fprintf(stdout, "Server is working ...\n");
while (1)
{
pthread_t thread;
pthread_create(&thread, NULL, clients_service, (void*)&clientsCounter);
}
return 0;
}
compile it like this: g++ -Wall -pthread echoserver.cpp -o echoserver
echoclient.c
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int client_to_server;
char *myfifo = "/tmp/client2server";
int server_to_client;
char *myfifo2 = "/tmp/server2client";
char str[255];
/* write str to the FIFO */
client_to_server = open(myfifo, O_WRONLY);
server_to_client = open(myfifo2, O_RDONLY);
while(1)
{
printf("\n> ");
scanf("%s", str);
write(client_to_server, str, sizeof(str));
read(server_to_client,str,sizeof(str));
printf("From server: %s\n",str);
}
close(client_to_server);
close(server_to_client);
/* remove the FIFO */
unlink("/tmp/server2client");
unlink("/tmp/client2server");
return 0;
}
compile it like this: gcc echoclient.c -o echoclient
To setup multiple connections you need multiple independend instances of a connection. An instance of a connection is represented by a fifo representing itself as a named entry in the file system.
To differentiate between those instances of the connecting channels their identifying names need to be different. In your code they are not. Each cleint uses the same fifos to communicate with server and verse vica.
Change your code to make the fifos' file system entries be named differently for each client.
Think over how it worked using sockets:
To replace this using fifos there need to be:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.