我正在使用 Winsock API 在 C++ 中创建服务器。我想知道是否只有在某些连接实际到来时才调用accept()函数,所以我不必在accept()上阻塞我的线程。换句话说,我想让我的线程等待并仅在客户端尝试连接时调用 accept() 函数。那可能吗?
问问题
1533 次
1 回答
0
当您使用 Winsock 时,您可以使用 Microsoft 特定的扩展功能AcceptEx
。这允许您将接受作为“重叠 I/O”执行,这在概念上意味着接受在后台运行,您可以偶尔进入并检查它是否发生,方法是检查OverlappedResult
,或执行等待在重叠句柄上。AcceptEx
还可以选择执行第一次接收。
在不编写所有代码并对其进行彻底测试的情况下,类似以下的内容应该可以工作:
// The following:
// Has no error checking
// Assumes sListen is a bound listening socket
// Some other assumptions I've not listed :)
// Allocate space to store the two sockaddr's that AcceptEx will give you
//
char lpOutputBuffer[sizeof((sockaddr_in)+16) * 2];
SOCKET sAccept = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
WSAOVERLAPPED olOverlap;
ZeroMemory(&olOverlap, sizeof(WSAOVERLAPPED));
olOverlap.hEvent = WSACreateEvent();
DWORD dwBytes;
BOOL bAcceptRet =
AcceptEx(sListen, // the listen socket
sAccept, // the socket to use for the accepted connection
lpOutputBuffer, // where to store the received information
0, // don't do a receive, just store the local and remote addresses
sizeof((sockaddr_in)+16), // size of the local address area
sizeof((sockaddr_in)+16), // size of the remote address area
&dwBytes, // set to received bytes if we complete synchronously
&olOverlap); // our overlapped structure
if (bAcceptRet) {
// the function completed synchronously.
// lpOutputBuffer should contain the address information.
// sAccept should be a connected socket
} else {
// the function didn't complete synchronously, so is the accept Pending?
if (ERROR_IO_PENDING == WSAGetLastError()) {
// in this case, our Accept hasn't happened yet...
// later in our code we can do the following to check if an accept has occurred:
// note that the FALSE tells WSAGetOverlappedResult not to wait for the I/O to complete
// it should return immediately
...
DWORD dwFlags;
if (WSAGetOverlappedResult(sListen, &olOverlap, &dwBytes, FALSE, &dwFlags)) {
// the accept has succeeded, so do whatever we need to do with sAccept.
}
...
}
}
当然,这是一个非常快速的、被破解的可能无法工作、不可编译的代码,但它应该让您了解如何执行与您想要的类似的事情,以及在哪里查看。
hEvent
顺便说一句,设置结构的参数在技术上不是必需的WSAOVERLAPPED
,但这样做可以让您真正等待请求完成:
if (WAIT_OBJECT_0 == WaitForSingleObject(olOverlap.hEvent, INFINITE)) {
// The accept occurred, so do something with it
}
我现在将等待有人指出我的代码中巨大的明显错误......
于 2013-06-12T11:28:12.797 回答