我遇到一些问题,将我的阻塞套接字服务器重写为非阻塞版本。 其实,我似乎甚至不能连接套接字,我一直在谷歌search今天的大部分,尝试不同的解决scheme,我发现这里和那里,但没有一个似乎正常工作…目前我的服务器循环只是不断调用select()调用,而不接受新的套接字。 客户端套接字似乎在某种程度上连接,因为如果我启动它,它将阻止尝试写入,如果我closures了服务器,它会通知该连接已被同级重置。
以下是一个正确的假设吗? 对于非阻塞服务器,我通常应该打开套接字,然后将它的标志设置为非阻塞,绑定它,并开始调用select读取文件描述符,并等待它填充? 我需要删除旧的阻塞“accept()”调用,这是无休止地等待。如果我尝试调用accept,现在我会-1 …
这是我正在尝试的相关代码
fd_set incoming_sockets; .... int listener_socket, newsockfd, portno; socklen_t clilen; struct sockaddr_in serv_addr, cli_addr; .... listener_socket = socket(AF_INET, SOCK_STREAM, 0); //get socket handle int flags = fcntl(listener_socket, F_GETFL, 0); if( fcntl(listener_socket, F_SETFL, flags | O_NONBLOCK) < 0 ) log_writer->write_to_error_log("Error setting listening socket to non blocking", false); memset(&serv_addr, 0, sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); .... if (bind(listener_socket, (struct sockaddr *) &serv_addr, sizeof(struct sockaddr_in)) < 0) { log_writer->write_to_error_log("Unable to bind socket, aborting!", true); } .... struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; int ready_sockets = 0; listen(listener_socket,1); FD_ZERO(&incoming_sockets); FD_SET(listener_socket, &incoming_sockets); while(true) { ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout ); if(ready_sockets == 0) { //I loop here now for ever std::cout << "no new sockets available, snooze 2\n"; sleep(2); } else { std::cout << "connection received!\n";
既然你不显示整个循环,我不知道你以后做了什么,但是你应该在每次调用select
之前初始化描述符集和超时结构。
您应该移动循环内的fd_zero()fd_set()宏,select将实际更改 fd_sets(和超时值)中的位掩码。 在每次迭代中重新初始化它们。 还检查选择返回-1和相关的errno(EPIPE …)
while(true) { FD_ZERO(&incoming_sockets); FD_SET(listener_socket, &incoming_sockets); ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout ); if(ready_sockets == 0) { ... }