有人可以用WinSock解释可写和可读fd_sets的功能吗?

Posted

技术标签:

【中文标题】有人可以用WinSock解释可写和可读fd_sets的功能吗?【英文标题】:Can someone explain the function of writeable and readable fd_sets with WinSock? 【发布时间】:2015-11-30 22:08:42 【问题描述】:

我正在为一个大学项目编写一个网络游戏,虽然我在客户端和服务器之间发送和接收消息,但我不确定如何实施 writeable fd_set(我的讲师的示例代码仅包含readable fd_set) 以及带有select() 的两个fd_set 的功能。您可以提供的任何见解都将有助于我理解这一点。

我的服务器代码是这样的:

bool ServerSocket::Update() 
    // Update the connections with the server

    fd_set readable;
    FD_ZERO(&readable);

    // Add server socket, which will be readable if there's a new connection
    FD_SET(m_socket, &readable);

    // Add connected clients' sockets
    if(!AddConnectedClients(&readable)) 
        Error("Couldn't add connected clients to fd_set.");
        return false;
    

    // Set timeout to wait for something to happen (0.5 seconds)
    timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 500000;

    // Wait for the socket to become readable
    int count = select(0, &readable, NULL, NULL, &timeout);
    if(count == SOCKET_ERROR) 
        Error("Select failed, socket error.");
        return false;
    

    // Accept new connection to the server socket if readable
    if(FD_ISSET(m_socket, &readable)) 
        if(!AddNewClient()) 
            return false;
        
    

    // Check all clients to see if there are messages to be read
    if(!CheckClients(&readable)) 
        return false;
    

    return true;

【问题讨论】:

相关answer 【参考方案1】:

您将创建一个名为writeablefd_set 变量,以相同的方式初始化它(使用相同的套接字),并将其作为select 的第三个参数传递:

select(0, &readable, &writeable, NULL, &timeout);

然后在select 返回后,您将检查每个套接字是否仍在集合writeable 中。如果是,那么它是可写的。

基本上,readable 的工作方式完全相同,只是它告诉您关于套接字的不同之处。

【讨论】:

这对我来说很有意义。我不完全理解的是为什么我需要找出套接字是否可写。是不是每当我发送一条消息时我都需要检查它是否可写? @DeanoMachino send 可以阻止,就像recv。因此,与您想要确定套接字是否可读的原因类似 - 它只是不太重要,因为 send 阻塞的频率低于 recv【参考方案2】:

一个套接字变成:

如果套接字接收缓冲区中有数据或待处理的 FIN(recv() 即将返回零),则可读 如果套接字接收缓冲区中有空间,则可写。请注意,几乎所有时间都是如此,因此您应该仅在套接字上遇到先前的 EWOULDBLOCK/EAGAIN 时使用它,并在没有遇到时停止使用它。

【讨论】:

好吧,这不能回答 OP 问题。 OP 没有询问套接字可写意味着什么,OP 询问如何轮询可写状态。说“套接字一直是可写的”也是非常错误的。显然,您从未处理过快速生产者/慢消费者案例。 @Sergey OP 准确地问了这个问题,我并没有说出你从我的话中捏造的错误引用。我请您参考问题的标题,在文本中重复,viz“有人可以解释可写和可读 fd_sets 的功能”,以及我实际写的内容。【参考方案3】:

select() 已经非常过时了,它的界面很神秘。 poll(或它的 windows 对应物 WSAPoll 是它的现代替代品,应该始终首选。

它将以下列方式使用:

WSAPOLLFD pollfd = m_socket, POLLWRNORM, 0;
int rc = WSAPoll(&pollfd, 1, 100);
if (rc == 1) 
   // Socket is ready for writing!

【讨论】:

不以任何方式回答问题。 @EJP,怎么会这样?它完美地告诉 OP 如何轮询可写套接字,并将 OP 引导到适当的功能。看不到它是如何“不回答问题”的。 问题是'有人可以解释可写和可读 fd_sets 的功能'。你在这里什么都没解释。

以上是关于有人可以用WinSock解释可写和可读fd_sets的功能吗?的主要内容,如果未能解决你的问题,请参考以下文章

chownchgrp和chmod的用法

linux可读可写权限

在 CoreBluetooth.framework 中实现读/写特性

I2C 文件描述符上的 I2C 总线可写/可读标志

centos7基础(持续更新)

select()函数