【发布时间】:2016-04-05 01:37:21
【问题描述】:
我在设置select() 和write_fds 时一定做错了。目前,当我第一次调用sendData() 时,它会从缓冲区发送 117 个字节(全部)。然后立即再次调用它,即使缓冲区中没有更多数据要发送,它也会一直调用sendData()。
知道我在这里做错了什么吗?
int readData(int j){
return recv(j, buf , nbytes , 0);
}
int sendData(int j){
unsigned v = fcntl(j, F_GETFL, 0);
fcntl(j, F_SETFL, v | O_NONBLOCK);
return send(j, buf, nbytes, 0);
}
fd_set master;
fd_set read_fds;
fd_set write_fds;
int fdmax;
...
FD_ZERO(&master);
FD_SET(socket, &master);
fdmax = socket;
for(;;){
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
read_fds = master;
write_fds = master;
if(select(fdmax+1, &read_fds, &write_fds, NULL, NULL) == -1){
exit(4);
}
for(i = 0; i <= fdmax; i++){
if(FD_ISSET(i, &read_fds)){
if(i == socket){
// handle new connections
addrlen = sizeof remoteaddr;
newfd = accept(socket, (struct sockaddr *)&addr, &addrlen);
FD_SET(newfd, &master);
if(newfd > fdmax) fdmax = newfd;
}else{
// we got some data from a client
readData(i);
}
} else if(FD_ISSET(i, &write_fds)){
if(i != socket){
// send data when notified
sendData(i);
}
}
}
}
【问题讨论】:
-
嗯,别再调用你不想调用的代码了。
-
在覆盖来自
master的相同fd 集之前调用FD_ZERO是没有意义的。 -
@Barmar 感谢您指出这一点。
-
您要求
select在可以写入数据时唤醒。您已经可以写入数据,因此它会立即唤醒。然后你实际上并没有写任何数据,只是回到要求它在你可以写数据时唤醒......你仍然可以,所以它立即唤醒,等等。 -
@immibis 谢谢,我现在明白了那部分,但仍然不清楚处理这个问题的最佳方法是什么。你有一个应该如何做的例子吗?