使用FD_SET进行读写设置,以便在C中发送和接收数据

问题描述 投票:0回答:1

我有一个客户端和服务器,客户端运行select循环以在TCP和UDP连接之间进行多路复用。我正在尝试将我的TCP连接文件描述符添加到readwrite集,然后使用write集和使用read集启动一个消息交换。我与write集的消息通信工作正常,但read设置我无法这样做。

客户代码:

    char buf[256] = {};
    char buf_to_send[256] = {};
    int nfds, sd, r;
    fd_set rd, wr;
    int connect_init = 1;

/* I do the Connect Command here */

    FD_ZERO(&rd);
    FD_ZERO(&wr);

    FD_SET(sd, &rd);
    FD_SET(sd, &wr);

    nfds = sd;


    for(; ;){

       r = select(nfds + 1, &rd, &wr, NULL, NULL);

       if(connect_init == 0){

          if(FD_ISSET(sd, &rd)){    // this is not working, if I change rd to wr, it works!

          r = recv(sd, buf, sizeof(buf),0);
          printf("received buf  = %s", buf);
          sprintf(buf, "%s", "client_reply\n");
          send(sd, buf, strlen(buf), 0);

      }
   }
/* Everything below this works correctly */
if (connect_init){

   if(FD_ISSET(sd, &wr)){

     sprintf(buf_to_send, "%s", "Client connect request");
     write(sd, buf_to_send, strlen(buf_to_send)); 

     recv(sd, buf, sizeof(buf), 0);
     printf("Server said = %s", buf);  

     sprintf(buf_to_send, "Hello!\n"); // client Hellos back
     send(sd, buf_to_send, strlen(buf_to_send), 0);

   }
   connect_init = 0;
  }

} // for loops ends
c sockets loops posix-select
1个回答
4
投票

每次调用select之前,都需要在循环中初始化集合。这是必要的,因为select修改它们。 Beej's Guide to Network Programming has a comprehensive example在一种方式使用select

所以在你的代码中,似乎select首先返回,允许写入,但读取没有,读取位重置为0,然后没有什么可以将它设置回1,因为从那时起select将不会触及它,因为它已经是0了。

如果select API困扰你,看看poll,它避免了这一点(注意,可能没有实际/效率差异,它基本上归结为个人偏好)。在具有许多描述符的“真实”代码(例如具有许多客户端的网络服务器)上,性能很重要,您应该使用其他一些机制,可能是某些更高级别的事件库,然后使用特定于操作系统的系统API,例如Linux的epoll facility。但只检查几个描述符,select是经过验证的真实且相对便携的选择。

© www.soinside.com 2019 - 2024. All rights reserved.