【问题标题】:Checking sockets using select() - Winsock使用 select() 检查套接字 - Winsock
【发布时间】:2014-08-11 03:56:40
【问题描述】:

我一直在探索函数select() 以检查是否有一些套接字已准备好读取,我必须承认我有点困惑。 MSDN 说“选择函数返回准备就绪并包含在fd_set 结构中的套接字句柄的总数”。

假设我有 3 个套接字并且 2 个套接字已准备就绪,select() 返回 2,但这没有告诉我这 3 个套接字中的哪两个已准备好读取,那么我该如何检查呢?

在堆栈溢出时我遇到了这个:When select returns, it has updated the sets to show which file descriptors have become ready for read/write/exception

所以我在我的程序中设置了断点来跟踪我的fd_set 结构。我意识到的是(fd_set 中只有一个套接字):如果套接字已准备好读取 select()

  1. 返回 1
  2. 保持fd_count(集合中的套接字数量)不变
  3. 保持fd_array(集合中的一组套接字。)保持不变

如果客户端没有发送任何寻址到该套接字select()的数据:

  1. 返回 0
  2. fd_count 减少到 0
  3. 保持fd_array不变

如果我再次调用 select() 并且客户端再次没有发送数据:

  1. return -1 (我认为这是因为fd_count 值 - 0)

我想我错过了一些关键规则 select() 的工作原理以及此函数的作用,但我无法弄清楚。 这是一些代码 sn-p 来显示我调用 select() 的操作:

CServer::CServer(char *ipAddress,short int portNumber)
{   // Creating socket
    ServerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (ServerSocket == INVALID_SOCKET) 
        std::cout << "I was not able to create  ServerSocket\n";
    else 
        std::cout << "ServerSocket created successfully\n";

    // Initialization of ServerSocket Address
    ServerSocketAddress.sin_family = AF_INET;
    ServerSocketAddress.sin_addr.S_un.S_addr = inet_addr(ipAddress);
    ServerSocketAddress.sin_port = htons(portNumber);
    // Binding ServerSocket to ServerSocket Address
    if (bind(ServerSocket, (SOCKADDR*)&ServerSocketAddress, sizeof(ServerSocketAddress)) == 0) 
        std::cout << "Binding ServersSocket and ServerSocketAddress ended with success\n";
    else 
        std::cout << "There were problems with binding ServerSocket and ServerSocket Address\n";

    // Initialization of the set of sockets
    ServerSet.fd_count = 1;
    ServerSet.fd_array[0] = ServerSocket;
}

主要:

CServer Server(IP_LOOPBACK_ADDRESS, 500);
tmp = select(0, &Server.ServerSet, NULL, NULL, &TimeOut);

select()调用之后,当没有可以读取的套接字时,fd_array不应该填充0值吗?

【问题讨论】:

    标签: sockets winsock


    【解决方案1】:

    您应该使用FD_SET 宏和朋友。你没有这样做。

    【讨论】:

    • 替换:ServerSet.fd_count = 1; ServerSet.fd_array[0] = ServerSocket; FD_ZERO(&Server.ServerSet); FD_SET(Server.ServerSocket, &Server.ServerSet);当我按照上面提到的顺序调用 select() 3 次时不会改变任何东西。
    • 您应该每次在循环中调用它。 select() 破坏性地使用它。
    • 当我每次在 select() 调用之前调用它时它都有效。如果我在 fd_set 中有 2 个套接字并且 select() 返回 1 我应该如何知道哪个套接字已准备好被读取? fd_array 中还有 2 个文件描述符。
    • 好的 FD_ISSET 工作,但如何!?。假设我有: fd_set myset; FD_SET(socket1,&myset); FD_SET(socket2,&myset);然后在调试器的本地窗口中,我可以看到:myset.fd_count = 2, myset.fd_array[0] = 124, myset.fd_array[1] = 136;。调用 select() 后,我可以看到 myset.fd_count = 1, myset.fd_array[0] = 124, myset.fd_array[1] = 136;。但是当我调用 FD_ISSET(Socket1,&myset) 我得到非零值,当我调用 FD_ISSET(Socket2,&myset) 我得到 0 值。我的问题是:如果只改变 myset.fd_count 值怎么可能?
    • fd_arrayfd_count 已更改以反映满足 select() 的套接字。 select() 根本没有清除fd_count 中未包含的阵列槽。这是您的代码不应该关心的实现细节。 FD_ISSET() 考虑到fd_count。在调用 select() 之前,您需要为放入数组中的每个套接字调用 FD_ISSET()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    相关资源
    最近更新 更多