首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用FD_SET制作读写集,用C语言收发数据

用FD_SET制作读写集,用C语言收发数据
EN

Stack Overflow用户
提问于 2013-11-03 06:57:13
回答 1查看 6.5K关注 0票数 1

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

客户代码:

代码语言:javascript
复制
    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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-03 07:00:47

每次调用select之前,都需要初始化循环中的集合。这是必要的,因为select会修改它们。Beej的网络编程指南有一个全面的例子是使用select的一种方式。

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

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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19750584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档