Winsock 的 connect() 函数超时
Timeout in connect() function from Winsock
有什么方法可以减少从 Winsock 调用 connect() 函数时的超时时间?
我觉得快30秒了,我想放5秒
最简单的方法是在连接时使用非阻塞模式的套接字,并使用select()
超时5秒来检查套接字是否可写。 select()
退出后,连接建立或不建立。如果没有,则认为连接超时,并根据需要进行错误处理。
您还可以调用 ConnectEx() 函数并将其传递给带有预创建事件的 OVERLAPPED.hEvent 结构,为此您可以使用 WaitForSingleObject() 等待任意短的时间。
ConnectEx() 仅适用于 WindowsXP 及更高版本...
//The HANDLE Socket MUST BE pre-bound with Bind() before calling this function
int ConnectWithTimout(HANDLE Socket, UINT remIP, WORD remPort, UINT milliseconds)
{
int iRes, Result;
UINT OptVal, Flags;
OVERLAPPED Overlapped;
sockaddr_in socket_info;
Result= ERROR_UNEXP_NET_ERR;
ZeroMemory(&socket_info, sizeof(socket_info));
ZeroMemory(&Overlapped, sizeof(Overlapped));
socket_info.sin_addr.S_addr = htonl(remIP);
socket_info.sin_port = htons(remPort);
socket_info.sin_family = AF_INET;
Overlapped.hEvent = WSACreateEvent();
if ( ConnectEx(Socket, &socket_info, sizeof(socket_info), NULL, 0, NULL, &Overlapped) )
printf("WOW! Connection succeeded immediately\n");
else
{
iRes = WSAGetLastError();
if (iRes == ERROR_IO_PENDING)
{
iRes = WaitForSingleObject(Overlapped.hEvent, milliseconds); //Wait for x milliseconds to connect
if (iRes == WAIT_OBJECT_0)
{
if (!WSAGetOverlappedResult(socket, &Overlapped, &OptVal, FALSE, Flags))
{
iRes = WSAGetLastError();
if (iRes == WSAEADDRINUSE)
DoError("WSAGetOverlappedResult() reported that the requested local address is already in use or in a TIME_WAIT state")
else
DoError("WSAGetOverlappedResult() failed with error: ", iRes);
}
else
{
OptVal = 1;
iRes = setsockopt(Socket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, PCHAR(&OptVal), sizeof(OptVal));
if (iRes == SOCKET_ERROR)
DoError("setsockopt(SO_UPDATE_CONNECT_CONTEXT) failed with error: ", WSAGetLastError() );
printf("Connected to %s : %s\n", inet_ntoa(socket_info.sin_addr), itoa(ntohs(socket_info.sin_port)));
Result=NO_ERROR;
}
}
else
{
if (iRes == WAIT_TIMEOUT)
{
DoWarning("ConnectEx() TIMED OUT - ", iRes);
Result= ERROR_TIMEOUT;
}
else
DoError("ConnectEx() failed with error: ", iRes)
}
}
else if (iRes == WSAECONNREFUSED) //After this error, it is OK to try to connect again on this docket.
DoWarning("ConnectEx() failed with CONNECTION REFUSED: ", 0 )
else if (iRes = WSAENETUNREACH) //After this error, it is OK to try to connect again on this docket.
DoWarning("ConnectEx() failed with NETWORK UNREACHABLE: ", 0 )
else if (iRes = WSAETIMEDOUT) //After this error, it is OK to try to connect again on this docket.
{
DoWarning("ConnectEx() TIMED OUT Immediately:", 0 );
Result= ERROR_TIMEOUT;
}
else
DoError("ConnectEx() failed with unexpected error: ", iRes )
}
WSACloseEvent(Overlapped.hEvent);
return Result;
}
有什么方法可以减少从 Winsock 调用 connect() 函数时的超时时间? 我觉得快30秒了,我想放5秒
最简单的方法是在连接时使用非阻塞模式的套接字,并使用select()
超时5秒来检查套接字是否可写。 select()
退出后,连接建立或不建立。如果没有,则认为连接超时,并根据需要进行错误处理。
您还可以调用 ConnectEx() 函数并将其传递给带有预创建事件的 OVERLAPPED.hEvent 结构,为此您可以使用 WaitForSingleObject() 等待任意短的时间。
ConnectEx() 仅适用于 WindowsXP 及更高版本...
//The HANDLE Socket MUST BE pre-bound with Bind() before calling this function
int ConnectWithTimout(HANDLE Socket, UINT remIP, WORD remPort, UINT milliseconds)
{
int iRes, Result;
UINT OptVal, Flags;
OVERLAPPED Overlapped;
sockaddr_in socket_info;
Result= ERROR_UNEXP_NET_ERR;
ZeroMemory(&socket_info, sizeof(socket_info));
ZeroMemory(&Overlapped, sizeof(Overlapped));
socket_info.sin_addr.S_addr = htonl(remIP);
socket_info.sin_port = htons(remPort);
socket_info.sin_family = AF_INET;
Overlapped.hEvent = WSACreateEvent();
if ( ConnectEx(Socket, &socket_info, sizeof(socket_info), NULL, 0, NULL, &Overlapped) )
printf("WOW! Connection succeeded immediately\n");
else
{
iRes = WSAGetLastError();
if (iRes == ERROR_IO_PENDING)
{
iRes = WaitForSingleObject(Overlapped.hEvent, milliseconds); //Wait for x milliseconds to connect
if (iRes == WAIT_OBJECT_0)
{
if (!WSAGetOverlappedResult(socket, &Overlapped, &OptVal, FALSE, Flags))
{
iRes = WSAGetLastError();
if (iRes == WSAEADDRINUSE)
DoError("WSAGetOverlappedResult() reported that the requested local address is already in use or in a TIME_WAIT state")
else
DoError("WSAGetOverlappedResult() failed with error: ", iRes);
}
else
{
OptVal = 1;
iRes = setsockopt(Socket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, PCHAR(&OptVal), sizeof(OptVal));
if (iRes == SOCKET_ERROR)
DoError("setsockopt(SO_UPDATE_CONNECT_CONTEXT) failed with error: ", WSAGetLastError() );
printf("Connected to %s : %s\n", inet_ntoa(socket_info.sin_addr), itoa(ntohs(socket_info.sin_port)));
Result=NO_ERROR;
}
}
else
{
if (iRes == WAIT_TIMEOUT)
{
DoWarning("ConnectEx() TIMED OUT - ", iRes);
Result= ERROR_TIMEOUT;
}
else
DoError("ConnectEx() failed with error: ", iRes)
}
}
else if (iRes == WSAECONNREFUSED) //After this error, it is OK to try to connect again on this docket.
DoWarning("ConnectEx() failed with CONNECTION REFUSED: ", 0 )
else if (iRes = WSAENETUNREACH) //After this error, it is OK to try to connect again on this docket.
DoWarning("ConnectEx() failed with NETWORK UNREACHABLE: ", 0 )
else if (iRes = WSAETIMEDOUT) //After this error, it is OK to try to connect again on this docket.
{
DoWarning("ConnectEx() TIMED OUT Immediately:", 0 );
Result= ERROR_TIMEOUT;
}
else
DoError("ConnectEx() failed with unexpected error: ", iRes )
}
WSACloseEvent(Overlapped.hEvent);
return Result;
}