簡體   English   中英

C/C++ sockets 和非阻塞 recv()

[英]C/C++ sockets and a non-blocking recv()

我遇到了調用 recv() 系統調用不會阻塞的問題。 我目前有一個客戶端-服務器結構設置,我遇到的問題是我向服務器發送一條消息,而服務器已設置為類似於:

while (1) {
   char buf[1024];
   recv(fd, buf, sizeof(buf), flags);
   processMsg(buf);
}

它正確接收第一條消息,但 recv() 不會阻止並“接收”不是所需的垃圾數據。 我只想在消息發送時對消息做出反應。 任何人都可以建議嗎?

recv() 在完成完整請求之前不一定會阻塞,但可以返回部分請求。 返回代碼將通知您實際收到的字節數可能少於您的請求。 即使您指定了 MSG_WAITALL 標志,它也可能由於信號等原因返回較少。

在 posix 系統上,在阻塞模式下 recv 只會阻塞,直到有一些數據被讀取。 然后,它將返回可能少於請求的數據,最多為請求的數量。 在非阻塞模式下,如果要讀取的數據為零字節,recv 將立即返回,並將返回 -1,將 errno 設置為 EAGAIN 或 EWOULDBLOCK。

結果是通常你會在一個循環中調用recv,直到你得到你想要的數量,同時還要檢查0(另一端斷開連接)或-1(一些錯誤)的返回碼。

我無法談論 windows 的行為。

有兩種可能性:要么發生錯誤,要么套接字設置為非阻塞模式。 要查看是否發生錯誤,請檢查recv的返回值:

while() {
    char buf[1024];
    int ret = recv(,buf,,)

    if(ret < 0) {
        // handle error
        printf("recv error: %s\n", strerror(errno));
    } else {
        // only use the first ret bytes of buf
        processMsg(buf, ret);
    }
}

要將套接字置於非阻塞模式,或查詢套接字是否處於非阻塞模式,請使用帶有O_NONBLOCK標志的fcntl(2)

// Test if the socket is in non-blocking mode:
if(fcntl(sockfd, F_GETFL) & O_NONBLOCK) {
    // socket is non-blocking
}

// Put the socket in non-blocking mode:
if(fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK) < 0) {
    // handle error
}

請注意,除非您明確更改阻塞行為,否則套接字默認情況下應該是阻塞的,因此很可能會發生錯誤。

如果您使用的是 windows,請運行 wsagetlasterror() function 並查看返回值。

http://msdn.microsoft.com/en-us/library/ms741580%28v=vs.85%29.aspx

如果您使用的是 posix 兼容系統,請查看 errno

http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html

暫無
暫無

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

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