【问题标题】:concurrent server TCP with select in c并发服务器 TCP 与 c 中的选择
【发布时间】:2018-07-14 13:54:24
【问题描述】:

我有一个小问题,实际上我必须让两个客户端与我的并发服务器通信(它们执行不同的功能),

我发现我可以使用 select 解决这个问题,但是如果我尝试在代码中实现它,它会给我一个分段错误,有人可以帮助我吗?

我声明以前只有一个客户端是一个寓言,现在不幸的是实现了选择,我有点宠坏了,

我应该解决这个问题,你可以用select()做一个并发服务器吗? 你能告诉我这段代码哪里错了吗?

int main (int argc , char *argv[])
{
 int list_fd,conn_fd;
 int i,j;
 struct sockaddr_in serv_add,client;
 char buffer [1024];
 socklen_t len;
 time_t timeval;
 char fd_open[FD_SETSIZE];
 pid_t pid;
 int logging = 1;
 char swi;
 fd_set fset;
 int max_fd = 0;
 int waiting = 0;
 int compat = 0;

 sqlite3 *db;
 sqlite3_open("Prova.db", &db);

    start2();
    start3();

    printf("ServerREP Avviato \n");

    if ( ( list_fd = socket(AF_INET, SOCK_STREAM, 0) ) < 0 ) {
        perror("socket");
        exit(1);
    }

    if (setsockopt(list_fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
        perror("setsockopt(SO_REUSEADDR) failed");

  memset((void *)&serv_add, 0, sizeof(serv_add));   /* clear server address */
  serv_add.sin_family      = AF_INET;
  serv_add.sin_port        = htons(SERVERS_PORT2);
  serv_add.sin_addr.s_addr = inet_addr(SERVERS_IP2);


    if ( bind(list_fd, (struct sockaddr *) &serv_add, sizeof(serv_add)) < 0 ) {
       perror("bind");
        exit(1);
    }

    if ( listen(list_fd, 1024) < 0 ) {
        perror("listen");
        exit(1);
    }

    /* initialize all needed variables */
    memset(fd_open, 0, FD_SETSIZE);   /* clear array of open files */
    max_fd = list_fd;                 /* maximum now is listening socket */
    fd_open[max_fd] = 1;

    //max_fd = max(conn_fd, sockMED);
        while (1) { 
            FD_ZERO(&fset);
            FD_SET(conn_fd, &fset);
            FD_SET(sockMED, &fset);
            len = sizeof(client);

            if(select(max_fd + 1, &fset, NULL, NULL, NULL) < 0){exit(1);}

            if(FD_ISSET(conn_fd, &fset))
            { 
                if ( (conn_fd = accept(list_fd, (struct sockaddr *)&client, &len)) <0 )
                perror("accept error"); 
                exit(-1); 
            } 
         /* fork to handle connection */ 
            if ( (pid = fork()) < 0 ){      
                perror("fork error"); 
                exit(-1); 
            } 
            if (pid == 0) {                 /* child */ 
                close(list_fd);
                close(sockMED); 
                Menu_2(db,conn_fd);
                close(conn_fd); 
                exit(0); 
            } else {                        /* parent */ 
                close(conn_fd); 
        } 
        if(FD_ISSET(sockMED, &fset))
        MenuMED(db,sockMED);
        FD_CLR(conn_fd, &fset);
        FD_CLR(sockMED, &fset);
    } 

    sqlite3_close(db); 
    exit(0); 
} 

【问题讨论】:

    标签: c select tcp server


    【解决方案1】:

    我不明白您在这里是如何尝试使用select,以及为什么要同时使用fork 让孩子处理接受的连接套接字,以及select

    常见的设计有:

    • 多处理服务器:

      父进程设置监听套接字并在等待实际连接时循环接受。然后它派出一个孩子来处理新接受的连接并简单地等待下一个。

    • 多线程服务器:

      前一个的变体。主线程启动一个新线程来处理新接受的连接,而不是分叉一个新进程。

    • 异步服务器:

      服务器设置fd_set 以了解哪些套接字需要处理。最初,只设置了监听套接字。然后主循环是(在伪代码中:

      loop on select
        if the listening socket is present in read ready sockets, accept the pending connection and add is to the `fd_set`, then return to loop
        if another socket is present in read ready socket
          read from it
          if a zero read (closed by peer), close the socket and remove it from the `fd_set`
          else process the request and return to loop
      

      这里的难点是处理时间长,整个过程被阻塞,并且处理涉及发送大量数据,发送部分也必须使用select...

    【讨论】:

      猜你喜欢
      • 2019-09-15
      • 2016-12-14
      • 2018-12-17
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 2013-02-06
      • 2020-09-14
      • 2020-09-17
      相关资源
      最近更新 更多