【问题标题】:Select function in non blocking sockets在非阻塞套接字中选择函数
【发布时间】:2014-07-27 01:02:45
【问题描述】:

我正在构建一个在线游戏客户端,当我尝试连接到离线服务器时,我的客户端冻结了,所以我想使用适合游戏的非阻塞套接字,因为在连接到服务器时需要完成其他任务.

在使用非阻塞套接字时,connect函数无论结果如何总是返回相同的值,所以这里的人们推荐使用select函数来查找连接请求的结果。

(连接前设置非阻塞socket)

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,为什么?

【问题讨论】:

  • Write 是否与 client.Write 相同? Err 是否与 client.Err 相同? hSocket 来自哪里?您在 iResult==0 情况下的错误消息不正确。
  • 如果iResult == -1 => msdn.microsoft.com/en-us/library/windows/desktop/…,您还应该检查WSAGetLastError 的错误代码
  • 是的,它与我所说的相同,它是我的代码的一部分,因为它不在一个文件中,不管它返回什么,但它总是返回相同的东西
  • 您之前是否调用过 WSAStartup ?

标签: c++ winsock


【解决方案1】:

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

如果select() 退出时套接字位于Err 集中,请使用getsockopt(SOL_SOCKET, SO_ERROR) 检索告诉您为什么connect() 失败的套接字错误代码。

if(iResult) 对任何非零值(包括 -1)评估为真。您需要改用 if(iResult > 0),因为 iResult 将报告在 any 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...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 2013-10-15
    • 2010-12-04
    相关资源
    最近更新 更多