我遇到了将阻塞套接字服务器重写为非阻塞版本的一些问题。 实际上,我似乎甚至不能连接套接字,我今天一直在谷歌搜索,并尝试不同的解决方案,我发现这里和那里,但它们似乎都没有正常工作...... 目前我的服务器循环只是保持超时的select()调用,没有接受新的套接字。 客户端套接字似乎在某种程度上连接,因为如果我启动它,它将阻止尝试写入,如果我关闭服务器,它将通知该连接已由对等方重置。
以下是正确的假设吗? 对于非阻塞服务器,我通常应该打开套接字,然后将它的标志设置为非阻塞,绑定它,并且开始调用select for read file descriptor并等待它填充? 我需要删除旧的阻止“accept()”调用,这是无休止地等待.. 如果我试着打电话给接受,那么现在我将对我进行判断......
以下是我正在尝试的相关代码
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";
答案 0 :(得分:1)
由于你没有显示整个循环,我不知道你以后是否这样做,但你应该在每次调用select
之前初始化描述符集和超时结构。
答案 1 :(得分:0)
你应该在循环中移动fd_zero()fd_set()宏 ,选择实际上更改 fd_sets中的位掩码(以及超时值)。在每次迭代时重新初始化它们。还要检查select return -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)
{
... }