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

时间:2012-12-02 10:11:06

标签: c++ c multithreading client-server

我想使用命名管道编写一个echo客户端 - 服务器应用程序(我用套接字做了它,它工作,但现在我想 使用命名管道执行相同操作。)服务器必须是多线程的。

当我第一次运行它时,我认为我的程序有效,这一切都很好。每个客户 连接到服务器从它收到一条消息。

但是现在,当我第二次尝试运行程序时,我仍然收到这条消息:

mkfifo client2server: File exists

(很多这样的消息)。当我试图运行时,这是我的输出./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

如何修复它按我想要的方式工作?制作真正的多线程echo服务器 - 客户端应用程序?

继承我的代码:

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;
}

像这样编译:{{1​​}}

echoclient.c

g++ -Wall -pthread echoserver.cpp -o echoserver

像这样编译:{{1​​}}

1 个答案:

答案 0 :(得分:1)

要设置多个连接,您需要连接的多个独立实例。连接的实例由fifo表示,fifo将自身表示为文件系统中的命名条目。

要区分连接通道的那些实例,它们的识别名称需要不同。在你的代码中,它们不是。每个cleint使用相同的fifos与服务器和维尼诗歌进行通信。

更改代码,使每个客户端的fifos'文件系统条目名称不同。

考虑使用套接字如何工作:

  • 服务器端有一个侦听套接字,接受所有客户端连接。
  • 由于接受连接一个特定客户端设置了特定套接字(允许双工通信)。

要使用fifos替换它,需要:

  • 一个替换侦听套接字
  • 为每个客户端连接提供的替换