我正在构建一个在线游戏客户端,当我尝试连接到离线服务器时,我的客户端冻结,因此我想使用适合游戏的非阻塞套接字,因为在连接到服务器时还需要完成其他任务
使用非阻塞套接字时,无论结果如何,connect
函数始终返回相同的值,因此此处的人员建议使用select
函数查找连接请求的结果。
(在连接前设置非阻塞套接字)
u_long iMode=1;
ioctlsocket(hSocket,FIONBIO,&iMode);
(设置套接字集)
FD_ZERO(&Write);
FD_ZERO(&Err);
FD_SET(hSocket, &Write);
FD_SET(hSocket, &Err);
TIMEVAL Timeout;
int TimeoutSec = 10; // timeout after 10 seconds
Timeout.tv_sec = TimeoutSec;
Timeout.tv_usec = 0;
int iResult = select(0, //ignored
NULL, //read
&(client.Write), //Write Check
&(client.Err), //Error Check
&Timeout);
if(iResult)
{
}
else
{
message_login("Error","Can't connect to the server");
}
select
函数总是返回-1,为什么?
答案 0 :(得分:2)
当select()
返回-1(SOCKET_ERROR
)时,请使用WSAGetLastError()
找出失败的原因。
如果套接字在Err
退出时select()
设置,请使用getsockopt(SOL_SOCKET, SO_ERROR)
检索套接字错误代码,告诉您connect()
失败的原因。
if(iResult)
的计算结果为true,包括-1。您需要使用if(iResult > 0)
,因为iResult
将报告在任何 fd_set
中发出信号的套接字数量,超时时为0,失败时为-1
尝试更像这样的东西:
u_long iMode = 1;
if (ioctlsocket(hSocket, FIONBIO, &iMode) == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
// use errCode as needed...
message_login("Error", "Can't set socket to non-blocking, error: ..."); // however you supply a variable value to your message...
}
if (connect(client.hSocket, ...) == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if (errCode != WSAEWOULDBLOCK)
{
// use errCode as needed...
message_login("Error", "Can't connect to the server, error: ..."); // however you supply a variable value...
}
else
{
// only in this condition can you now use select() to wait for connect() to finish...
}
}
TIMEVAL Timeout;
int TimeoutSec = 10; // timeout after 10 seconds
Timeout.tv_sec = TimeoutSec;
Timeout.tv_usec = 0;
int iResult = select(0, //ignored
NULL, //read
&(client.Write), //Write Check
&(client.Err), //Error Check
&Timeout);
if (iResult > 0)
{
if (FD_ISSET(client.hSocket, &(client.Err)))
{
DWORD errCode = 0;
int len = sizeof(errCode);
if (getsockopt(client.hSocket, SOL_SOCKET, SO_ERROR, (char*)&errCode, &len) == 0)
{
// use errCode as needed...
message_login("Error", "Can't connect to the server, error: ..."); // however you supply a variable value to your message...
}
else
message_login("Error", "Can't connect to the server, unknown reason");
}
else
message_login("Success", "Connected to the server");
}
else if (iResult == 0)
{
message_login("Error", "Timeout connecting to the server");
}
else
{
int errCode = WSAGetLastError();
// use errCode as needed...
message_login("Error", "Can't connect to the server, error: ..."); // however you supply a variable value to your message...
}