簡體   English   中英

C套接字中的非阻塞recv()

[英]Non Blocking recv() in C Sockets

我在套接字中使用一個無限循環,如果它接收到一些數據,它應該接收它,或者如果它想發送它發送的數據,則在其中。 如下所示。 我正在使用select。 我只有一個插槽SD。

fd_set readsd;
int maxsd = readsd +1;
// all those actions of setting maxsd to the maximum fd +1 and FDSETing the FDs.
while(1)
{
     FD_ZERO(&read_sd);
     FD_SET(sd, &read_sd);
     if(FD_ISSET(sd, &readsd))
     {
       //recv call
     }
     else
     {
       //send call
     }
}

據我所知,select選擇一個套接字描述符之一,數據首先到達該套接字描述符。 但是這里我只有一個套接字,如果有數據我想接收,否則我想發送。

在這種情況下,上面給出的代碼可以嗎? 還是我不知道的其他選擇?

在那種情況下,上面給出的代碼是否還可以?

我沒有看到任何要選擇的電話。 另外,如果將“ maxsd”設計為select的第一個參數,則其值是錯誤的:它必須是最大的文件描述符+1。 無論如何,您可以僅使用標志MSG_DONTWAIT調用recv,在這種情況下,如果沒有要讀取的數據,它將返回錯誤。

這取決於……首先,您實際上在實際代碼中確實有一個select調用嗎?

現在有關阻塞的問題...如果select返回時套接字已設置為讀集,那么可以保證可以調用recv而不會阻塞。 但是不能保證可用的數據量。 如果使用UDP,則將至少有一個(希望是完整的)數據包,但如果使用TCP,則可能只會得到一個字節。 對於某些具有消息邊界的協議,您可能不會收到完整的消息,因此必須循環調用recv才能獲取所有消息,但不幸的是,這遲早會導致recv調用阻塞。

簡而言之,使用select幫助,但並非在所有情況下都有用。 真正保證recv調用不會阻塞的唯一方法是使套接字變為非阻塞狀態。

我不太確定自己要做什么,因此我可以考慮以下兩種選擇:

將套接字設置為非阻塞

由於似乎您只有一個套接字,因此可以使用fcntl將套接字設置為非阻塞模式,然后調用recv()

fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
// if fcntl returns no error, sock is now non-blocking

設置選擇計時器

使用select可以設置一個計時器,即使沒有收到任何數據,也可以在一段時間后強制返回。

首先,我在您的代碼中找不到任何select

但是,您可以首先調用fcntl(fd, F_SETFL, flags | O_NONBLOCK)以使套接字無阻塞。 然后,當您無法從recv讀取任何內容時,檢查errno == EWOULDBLOCK 在這種情況下,您無需使用select

暫無
暫無

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

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