使用select和accept启动新文件描述符

时间:2013-09-27 03:08:55

标签: c sockets client-server

场景:当在一个套接字中选择检测活动时,我的代码中会出现以下条件。

伪代码:

after select i am checking in
if stdin f descriptor
    do something

else if listening file descriptor
newFDescriptor = accept sockFDescriptor, (struct sockaddr *) &clientAddress, &clientAddressSize

FD_SET (new file descriptor)
send connected response to peer

// data from connected peer
else {
    receive data
}

但是每次我从对等端向其他人发送内容时,它会与新的filedescriptor建立新的连接。即,它不会对已创建的此对等方的文件描述符中的数据进行重新识别。 peer 1 to peer 2(创建新文件描述符) 对等1对等2(再次新连接) 它正在接收侦听文件描述符上的所有数据。

2 个答案:

答案 0 :(得分:1)

如果对等方坚持创建新连接,那么在服务器端无法对此进行任何操作。

“它正在接收关于侦听文件描述符的所有数据”并没有开始有意义。不可能。除了接受连接之外,侦听文件描述符不能执行任何操作。

答案 1 :(得分:0)

我同意jedwards(+1) - 您应该阅读Beej指南以帮助您入门。

同时,这里有一些快速输入可能有助于避免您遇到的错误。我的猜测是你混淆了文件描述符。

您需要将新文件描述符(来自accept()调用的描述符)添加到列表中,然后使用它们(也)填充下一个select调用的fd set。监听器fd仅用于建立新连接和后续accept() - 您不应该在该fd上调用receive或send(让我们称之为server_fd)。

这是一个快速示例代码,用于存储数组中的所有连接,然后您可以按如下方式设置fd。对于没有有效fd的数组的索引,它使用-1。

FD_ZERO(&read_fd_set);
/* Set the fd_set before passing it to the select call */
for (i=0;i < MAX_CONNECTIONS;i++) {
   if (all_connections[i] >= 0) {
       FD_SET(all_connections[i], &read_fd_set);
   }
}

ret_val = select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL);

一旦select返回,你可以检查带有read-event的fd是否是服务器fd,如果是,你可以调用accept()来获取新的fd - 你需要将它添加到数组中。像这样:

if (FD_ISSET(server_fd, &read_fd_set)) { 
    new_fd = accept(server_fd, (struct sockaddr*)&new_addr, &addrlen);
    if (new_fd >= 0) {
        printf("Accepted a new connection with fd: %d\n", new_fd);
        for (i=0;i < MAX_CONNECTIONS;i++) {
             if (all_connections[i] < 0) {
                 all_connections[i] = new_fd; 
                 break;
             }
        }
    }
}