【发布时间】:2014-11-22 22:35:40
【问题描述】:
有两台socket服务器,一台是不常开的主服务器,一台是备用服务器。
我的程序将尝试使用非阻塞连接连接主服务器(以便可以应用超时值),如果失败,它将使用阻塞连接连接备份服务器。
但是第二个connect函数大部分时候会返回“Invalid argument”错误码:
#define SERVER_URL "example.com"
#define SERVER_PORT_PRIMARY "1234"
#define SERVER_PORT_BACKUP "5678"
struct addrinfo *result = NULL;
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(SERVER_URL , SERVER_PORT_PRIMARY , &hints, &result) != 0) {
WSACleanup();
return;
}
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socketClient == SOCKET_ERROR){
WSACleanup();
return;
}
//set the socket in non-blocking
unsigned long iMode = 1;
iResult = ioctlsocket(socketClient, FIONBIO, &iMode);
if (iResult != NO_ERROR){
closesocket(socketClient);
WSACleanup();
return;
}
if (connect(socketClient, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR){
if (WSAGetLastError() != WSAEWOULDBLOCK){
closesocket(socketClient);
WSACleanup();
return;
}
}
//switch it back to blocking socket
iMode = 0;
iResult = ioctlsocket(socketClient, FIONBIO, &iMode);
if (iResult != NO_ERROR){
closesocket(socketClient);
WSACleanup();
return;
}
fd_set Write, Err;
FD_ZERO(&Write);
FD_ZERO(&Err);
FD_SET(socketClient, &Write);
FD_SET(socketClient, &Err);
TIMEVAL Timeout;
Timeout.tv_sec = 10;
Timeout.tv_usec = 0;
select(0, NULL, &Write, &Err, &Timeout);
if (FD_ISSET(socketClient, &Write) == false){
//unable to connect to primary server within 10s, try to connect backup server
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(SERVER_URL , SERVER_PORT_BACKUP, &hints, &result) != 0) {
closesocket(socketClient);
WSACleanup();
return;
}
iResult = connect(socketClient, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR){
int a = WSAGetLastError(); ///<----Problem here, a == WSAEINVAL (Invalid argument)
closesocket(socketClient);
WSACleanup();
return;
}
}
正如我在上面的代码中评论的那样,第二次“连接”调用将在大多数情况下返回 SOCKET_ERROR,而 WSAGetLastError() 返回 WSAEINVAL(无效参数)。
如果我删除非阻塞代码,它将无错误地连接。那么我的代码有什么问题呢?
【问题讨论】:
标签: sockets nonblocking