我试图弄清楚为什么recv在下面的代码中被阻止,如果我通过telnet并发送“ GET / HTTP / 1.1”,则recv会一直在等待数据并阻止另一个telnet连接。但是,如果我只是使用固定的缓冲区而不是,它就可以正常工作并且不会阻塞do{} while
,即,
char buffer[1024];
nbytes = recv(i, buffer, sizeof buffer, 0);
到目前为止,我所了解的select()
处于准备就绪的状态。我需要设置recv
为O_NONBLOCK
吗?
char *buffer = NULL;
unsigned long LEN = 200;
unsigned long bytes_received = 0;
unsigned long cur_size = 0;
int status = 0;
FD_SET(listener, &master);
fdmax = listener;
for(;;){
read_fds = master; // copy it
if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){
exit(4);
}
for(i = 0; i <= fdmax; i++){
if(FD_ISSET(i, &read_fds)){
if(i == listener){
// handle new connections
addrlen = sizeof remoteaddr;
newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen);
if(newfd == -1){
perror("accept");
}else{
FD_SET(newfd, &master);
if(newfd > fdmax) {
fdmax = newfd;
}
}
}else{
do{
if(bytes_received >= cur_size){
char * tmp;
cur_size += LEN;
tmp = realloc(buffer, cur_size);
buffer = tmp;
}
status = recv(i, buffer + bytes_received, LEN, 0);
if(status == 0){
printf("Done\n");
}
else if(status > 0){
bytes_received += status;
}
else{
fprintf(stderr, "socket error\n");
}
} while (status > 0);
if(send(i, buffer, strlen(buffer), 0) == -1){
perror("send");
}
}
}
}
}
首先,如果您不想阻塞,则必须将套接字设置为非阻塞。无论您做什么,都无法确保如果套接字操作正在阻塞,则永远不会阻塞。这是一个常见的错误,已导致严重的错误,并带有重大的安全隐患。如果必须阻止,则必须将套接字设置为非阻止。
到目前为止,我了解到的是select()处于就绪状态。
您的意思是处于随时可以阅读的状态。该select
函数是一个状态报告功能,与其他状态报告功能一样,它会在调用它和返回它之间的某个时间点报告状态。无法保证在以后的某个时刻仍保持该状态。
永远不要认为您可以排除状态可能改变的所有其他可能方式。历史充满了那些认为并被焚毁的人。
但是阻塞的特定原因是您在recv
没有先调用的情况下进行调用select
(因为您有一个再次do
调用的循环recv
)。
无论如何,您都必须正确处理WOULDBLOCK
来自的指示recv
。那是必不可少的。
此外,您可能希望recv
每个select
匹配仅打一次电话。如果您解决了其他问题,那就没关系了。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句