我正在构建一个在线游戏客户端,当我尝试连接到脱机服务器时,客户端冻结了,因此我想使用适合游戏的非阻塞插槽,因为在连接服务器时还需要​​完成其他任务。

在使用非阻塞套接字时,不管结果如何,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,为什么呢?

最佳答案

select()返回-1(SOCKET_ERROR)时,请使用WSAGetLastError()找出失败的原因。

如果在Err退出时套接字位于select()中,请使用getsockopt(SOL_SOCKET, SO_ERROR)检索套接字错误代码,该代码将告诉您connect()失败的原因。
if(iResult)对任何非零值(包括-1)求值为true。您需要改用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...
}

关于c++ - 非阻塞 socket 中的选择功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24956235/

10-17 00:41