什么会导致非阻塞套接字在`recv`上阻塞?

问题描述 投票:-1回答:1

我有一个设置为非阻止的TCP / IP套接字,无论如何仍在阻止。该套接字仅在一个线程中引用。此代码在Windows(有一些呼叫替换)上有效,但在Linux上无效。我有看起来像这样的代码(不要介意C样式的强制转换-这是很久以前编写的。此外,我对其进行了一些修整,所以请告知是否意外修整了一步。 '实际上是在执行该步骤。实际代码在另一台计算机上,所以我无法复制粘贴。):

// In the real code, these are class members. I'm not bonkers
int mSocket;
sockaddr_in mAddress;

void CreateSocket(
    unsigned int ipAddress,
    unsigned short port)
{        
    // Omitting my error checking in this question for brevity because everything comes back valid
    mSocket = socket(AF_INET, SOCK_STREAM, 0);  // Not -1

    int oldFlags = fctnl(mSocket, F_GETFL, 0);  // Not -1
    fcntl(mSocket, F_SETFL, oldFlags | O_NONBLOCK);  // Not -1

    mAddress.sin_family = AF_INET;
    mAddress.sin_addr.s_addr = ipAddress;  // address is valid
    mAddress.sin_port = htons((u_short)port);  // port is not 0 and allowed on firewall
    memset(mAddress.sin_zero, 0, sizeof(mAddress.sin_zero));

    // <Connect attempt loop starts here>
    connect(mSocket, (sockaddr*)&mAddress, sizeof(mAddress));  // Not -1 to exit loop
    // <Connect attempt loop ends here>
    // Connection is now successful ('connect' returned a value other than -1)
}

// ... Stuff happens ...

// ... Then this is called because 'select' call shows read data available ...
void AttemptReceive(
    MyReturnBufferTypeThatsNotImportant &returnedBytes)
{
    // Read socket
    const size_t bufferSize = 4096;
    char buffer[bufferSize];
    int result = 0;

    do {
        // Debugging code: sanity checks
        int socketFlags = fcntl(mSocket, F_GETFL, 0);  // Not -1
        printf("result=%d\n", result);
        printf("O_NONBLOCK? %d\n", socketFlags & O_NONBLOCK);  // Always prints "O_NONBLOCK? 2048"

        result = recv(mSocket, buffer, bufferSize, 0);  // NEVER -1 or 0 after hundreds to thousands of calls, then suddenly blocks

        // ... Save off and package read data into user format for output to caller ...
    } while (result == bufferSize);
}

我相信,因为调用AttemptReceive是为了响应select,所以套接字恰好恰好包含等于缓冲区大小(4096)倍数的字节数。我已经通过printf语句对此进行了某种程度的确认,因此它永远不会在第一个循环中阻塞。每次发生此错误时,在线程块之前要打印的最后两行是:

result=4096
O_NONBLOCK? 2048

recv行更改为recv(mSocket, buffer, bufferSize, MSG_DONTWAIT);实际上“解决”了该问题(突然,recv偶尔会返回errno EWOULDBLOCK / EAGAIN -1(在我的操作系统上彼此相等)),但我恐怕是可以这么说,我只是将创可贴放在伤口上。有什么想法吗?

P.S。地址为“ localhost”,但我认为这无关紧要。

c++ linux sockets tcp blocking
1个回答
0
投票

[socket()会在我的操作系统和编译器上自动在套接字上设置O_RDWR,但是似乎O_RDWR在程序启动时意外地在相关套接字上被取消设置(以某种方式使它可以正常读取) (如果有要读取的数据,则阻止)。修复该错误导致套接字停止阻塞。显然,至少在我的操作系统和编译器上,都需要O_RDWRO_NONBLOCK来避免套接字阻塞。

© www.soinside.com 2019 - 2024. All rights reserved.