有人可以用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】:您将创建一个名为writeable
的fd_set
变量,以相同的方式初始化它(使用相同的套接字),并将其作为select
的第三个参数传递:
select(0, &readable, &writeable, NULL, &timeout);
然后在select
返回后,您将检查每个套接字是否仍在集合writeable
中。如果是,那么它是可写的。
基本上,readable
的工作方式完全相同,只是它告诉您关于套接字的不同之处。
【讨论】:
这对我来说很有意义。我不完全理解的是为什么我需要找出套接字是否可写。是不是每当我发送一条消息时我都需要检查它是否可写? @DeanoMachinosend
可以阻止,就像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的功能吗?的主要内容,如果未能解决你的问题,请参考以下文章