[英]Winsock C++ connect timeout
我正在嘗試為connect()函數設置自己的timeot。
我的代碼在默認連接中效果很好,如下所示:
bool connectFUNC4(char * ipaddr) {
WSADATA wsa;
struct sockaddr_in server;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return false;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return false;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_family = AF_INET;
server.sin_port = htons(5577);
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
return false;
return true;
}
我了解阻塞和不阻塞連接的想法,並且我找到了設置為非阻塞模式和超時的解決方案。 它總是成功完成,但是通信不起作用。
bool connectFUNC3(char * ipaddr) {
WSADATA wsa;
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_family = AF_INET;
server.sin_port = htons(5577);
unsigned long block = 1;
ioctlsocket((unsigned int)sock, FIONBIO, &block);
WSAGetLastError();
int ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
timeval time_out;
time_out.tv_sec = 5;
time_out.tv_usec = 0;
fd_set setW, setE;
FD_ZERO(&setW);
FD_SET(sock, &setW);
FD_ZERO(&setE);
FD_SET(sock, &setE);
select(0, NULL, &setW, &setE, &time_out);
bool flag;
if (FD_ISSET(sock, &setW))
{
// connection successful
flag = true;
}
else if (FD_ISSET(sock, &setE))
{
// connection fail
flag = false;
}
else
{
// connection timeout
flag = false;
}
block = 0;
ioctlsocket((unsigned int)sock, FIONBIO, &block);
return flag;
}
請幫助使其工作或找到其他解決方案(在我的情況下,多線程不可用)。 謝謝。
您的兩個函數都沒有檢查任何返回值是否有錯誤。 在非阻塞模式下調用select()
時,僅當connect()
失敗並出現WSAEWOULBLOCK
錯誤時才調用它,並且如果select()
然后返回> 0,則應首先檢查setE
而不是setW
。
嘗試更多類似這樣的方法:
void closesock(SOCKET *s)
{
// preserve current error code
int err = WSAGetLastError();
closesocket(*sock);
*sock = INVALID_SOCKET;
WSASetLastError(err);
}
bool connectFUNC4(char * ipaddr)
{
// you really shouldn't be calling WSAStartup() here.
// Call it at app startup instead...
struct sockaddr_in server = {0};
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_port = htons(5577);
// ipaddr valid?
if (server.sin_addr.s_addr == INADDR_NONE)
return false;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return false;
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
// connection failed
closesock(&sock);
return false;
}
// connection successful
return true;
}
bool connectFUNC3(char * ipaddr)
{
// you really shouldn't be calling WSAStartup() here.
// Call it at app startup instead...
struct sockaddr_in server = {0};
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_port = htons(5577);
// ipaddr valid?
if (server.sin_addr.s_addr == INADDR_NONE)
return false;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return false;
// put socked in non-blocking mode...
u_long block = 1;
if (ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR)
{
closesock(&sock);
return false;
}
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
// connection failed
closesock(&sock);
return false;
}
// connection pending
fd_set setW, setE;
FD_ZERO(&setW);
FD_SET(sock, &setW);
FD_ZERO(&setE);
FD_SET(sock, &setE);
timeval time_out = {0};
time_out.tv_sec = 5;
time_out.tv_usec = 0;
int ret = select(0, NULL, &setW, &setE, &time_out);
if (ret <= 0)
{
// select() failed or connection timed out
closesock(&sock);
if (ret == 0)
WSASetLastError(WSAETIMEDOUT);
return false;
}
if (FD_ISSET(sock, &setE))
{
// connection failed
int err = 0;
getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, sizeof(err));
closesock(&sock);
WSASetLastError(err);
return false;
}
}
// connection successful
// put socked in blocking mode...
block = 0;
if (ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR)
{
closesock(&sock);
return false;
}
return true;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.