如何在 x 时间后中止 Winsock 连接

How to abort Winsock connection after x time

本文关键字:Winsock 连接 时间      更新时间:2023-10-16

我目前正在开发自己的TeamSpeak3Bot。对于连接部分,我使用的是Microsoft的Winsock库。

连接建立如下:

// Initialize Winsock
WSAData winSockData;
WORD dllVersion = MAKEWORD(2, 1);
long iResult = WSAStartup(dllVersion, &winSockData);
if (iResult != NO_ERROR)
    return;
addrinfo* serverAddress = nullptr;
addrinfo* ptr = nullptr, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo("127.0.0.1", "10011", &hints, &serverAddress);
if (iResult != 0)
    return;
// Create communication socket
SOCKET connectSocket = socket(AF_INET, SOCK_STREAM, /*IPPROTO_TCP*/0);
if (connectSocket == INVALID_SOCKET)
    return;
// Establish connection to server
iResult = connect(connectSocket, serverAddress->ai_addr (int)serverAddress->ai_addrlen);
if (iResult == SOCKET_ERROR)
    return;
// server address info not needed anymore
freeaddrinfo(serverAddress);

由于 Winsock 的 send()recv() 函数首先等待相应的发送/接收操作完成,因此主线程在此期间暂停。

如何适当地检查recv()上收到的输入?,以及如何在特定时间(以毫秒为单位)过后中止recv()

注意:如果send()recv()超时,我还需要能够抛出特定于类的异常!

一种可能性是使用非阻塞套接字,然后您可以轮询。

您可以通过执行以下操作将套接字设置为非阻塞:

ULONG mode = 1;
int res = ioctlsocket(socket, FIONBIO, &mode);

这意味着如果那里没有任何东西,则调用 recv 会立即返回并返回WSAGetLastError() WSAEWOULDBLOCK .

您应该使用 select() 来等待输入可用。 这允许您指定超时。 当select()告诉您输入在套接字上可用时,您可以使用recv()读取它。