我有一个客户机和服务器,客户端运行一个select循环,在TCP和UDP连接之间进行多路复用。我正在尝试将我的TCP连接文件描述符添加到read和write集中,然后使用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发布于 2013-11-03 07:00:47
每次调用select之前,都需要初始化循环中的集合。这是必要的,因为select会修改它们。Beej的网络编程指南有一个全面的例子是使用select的一种方式。
因此,在您的代码中,似乎select首先返回允许写入,但不允许读取,这使读取位重置为0,然后没有什么可以将其设置为1,因为从那时起,select将不会触及它,因为它已经是0了。
如果select API困扰您,请看poll,它避免了这一点(请注意,可能没有实际/效率上的差异,基本上可以归结为个人偏好)。在具有许多描述符(例如具有许多客户端的网络服务器)的“真实”代码上,您应该使用一些其他机制,可能是一些更高级别的事件库,然后使用特定于操作系统的系统API,例如Linux的设施。但是,只要检查几个描述符,select就是一个尝试过的、真实的、相对可移植的选择。
https://stackoverflow.com/questions/19750584
复制相似问题