簡體   English   中英

如何在 Windows 中判斷套接字是否已經處於非阻塞模式?

[英]How to find out if a socket is already in Non-Blocking mode in Windows?

有沒有辦法找出Windows中的套接字是否已經處於非阻塞模式?

我知道這可以在 Linux 的情況下完成,但是,我無法為這個 Windows 找到任何方法。

我所有的編碼都是用“C”語言編寫的。 有辦法嗎?

您可以檢查此問題的唯一方法是在無阻塞套接字上執行非法操作,並檢查它是否以預期的方式失敗。 幾乎不是最可靠的設計。

除非使用WSAIoctlioctlsocketFIONBIO明確將其設置為非阻塞,否則該套接字將處於阻塞FIONBIO 我本以為,檢查代碼不會太難。 如果必須在運行時進行跟蹤,則可以按照@jweyrich的建議在每個套接字上標記。

只是在這里回答了相同的問題,所以這里有一個復制粘貼,希望對您有所幫助:

以前,您可以調用WSAIsBlocking來確定。 如果要管理舊代碼,則仍然可以選擇。

否則,您可以在套接字API上編寫一個簡單的抽象層。 由於默認情況下所有套接字都處於阻塞狀態,因此您可以維護一個內部標志,並通過API強制所有套接字操作,以便您始終知道狀態。

這是設置/獲取阻止模式的跨平台代碼段,盡管它不能完全滿足您在Windows上的要求:

/// @author Stephen Dunn
/// @date 10/12/15
bool set_blocking_mode(const int &socket, bool is_blocking)
{
    bool ret = true;

#ifdef WIN32
    /// @note windows sockets are created in blocking mode by default
    // currently on windows, there is no easy way to obtain the socket's current blocking mode since WSAIsBlocking was deprecated
    u_long flags = is_blocking ? 0 : 1;
    ret = NO_ERROR == ioctlsocket(socket, FIONBIO, &flags);
#else
    const int flags = fcntl(socket, F_GETFL, 0);
    if ((flags & O_NONBLOCK) && !is_blocking) { info("set_blocking_mode(): socket was already in non-blocking mode"); return ret; }
    if (!(flags & O_NONBLOCK) && is_blocking) { info("set_blocking_mode(): socket was already in blocking mode"); return ret; }
    ret = 0 == fcntl(socket, F_SETFL, is_blocking ? flags ^ O_NONBLOCK : flags | O_NONBLOCK);
#endif

    return ret;
}

從MSDN, connect()的返回值:

  • 阻塞套接字上,返回值指示連接嘗試成功或失敗。

  • 使用無阻塞套接字,無法立即完成連接嘗試。 在這種情況下,connect將返回SOCKET_ERROR ,而WSAGetLastError()將返回WSAEWOULDBLOCK

這並不理想,但這對我有用

static bool is_blocking(SOCKET s) {
    /*
     * Win32 does not have a method of testing if socket was put into non-blocking state.
     */
    DWORD timeout;
    DWORD fast_check = 1;
    int tolen = sizeof(timeout);
    getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, &tolen);
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *) &fast_check, sizeof(fast_check));
    char b;
    int r = recv(s, &b, 0, 0);
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(fast_check));

    if (r == 0)
        return true;
    else if (r == -1) {
        int err = WSAGetLastError();
        if (err == WSAEWOULDBLOCK) return false;
        if (err == WSAETIMEDOUT) return true;
    }
    return true;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM