简体   繁体   English

C和C ++中的简单回显客户端服务器

[英]Simple echo client-server in C and C++

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. 我想使用命名管道编写一个echo客户-服务器应用程序(我用套接字完成了它,它可以工作,但是现在我想对命名管道做同样的事情。)服务器必须是多线程的。

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时的输出:

$ ./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 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 像这样编译它: g++ -Wall -pthread echoserver.cpp -o echoserver

echoclient.c 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 像这样编译它: 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. 连接的实例由fifo表示,该fifo在文件系统中将自身表示为命名条目。

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. 每个部门都使用相同的fifo与服务器和vica通信。

Change your code to make the fifos' file system entries be named differently for each client. 更改您的代码,以使每个客户的fifos文件系统条目的名称都不同。

Think over how it worked using sockets: 考虑一下它如何使用套接字工作:

  • There is one listening socket on the server side accepting all client connects. 服务器端有一个侦听套接字,它接受所有客户端连接。
  • As the result of accepting a connection a specific socket is setup (allowing duplex communication) for one specific client ). 接受连接的结果是为一个特定的客户端设置了一个特定的套接字 (允许双工通信)。

To replace this using fifos there need to be: 要使用fifos替换此代码,需要:

  • one replacement for the listening socket 监听插座的一种替代
  • replacements for each socket serving each client connection. 服务于每个客户端连接的每个套接字的替换

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM