簡體   English   中英

套接字:為什么阻塞read()會因ENOTCONN而失敗?

[英]Sockets: Why does a blocking read() fail with ENOTCONN?

我試圖從阻塞套接字讀取,但我想知道read()返回-1,我認為這意味着當前沒有數據要讀取 - 我希望它會阻塞,直到它可以讀取字節數。

我還嘗試確保套接字處於阻塞模式,並使用以下命令設置高超時:

int setBlockingIO(int fd)
{
       int flags = fcntl(fd, F_GETFL);
       fcntl(fd, F_SETFL, flags & (~O_NONBLOCK));
       int nTimeout = 30000; // 30 seconds
       setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTimeout, sizeof(int));
}

但這並沒有改變任何事情。

我的問題:

  • 我必須做什么, read()really block?
  • 我可能會遇到一些陷阱嗎? (我的程序中的錯誤?)

我知道關於這個話題還有另一個問題 ,但在那里我找不到我的問題的答案。

UPDATE

如果沒有設置超時, read()也會立即返回(主觀)-1

更新2

errno是107( ENOTCONN, Transport endpoint is not connected) 但是客戶端同時沒有關閉連接sleep()write()之后通過長sleep()確保)

你能指望什么? 你說你有一個非阻塞套接字,所以它當然不會阻塞。 如果數據可供讀取,則read非阻塞套接字的行為將立即返回一些數據(可能短於請求的數量),如果沒有可用數據,則返回-1,其中errno設置為EAGAINEWOULDBLOCK

如果您不想要非阻塞行為,為什么要將套接字設置為非阻塞?

編輯:格爾,你已經改變了你的問題。 ENOTCONN的原因是您嘗試從未連接的套接字讀取。 除非通過acceptsocketpair獲得套接字,否則必須在其上調用connect以將其連接到遠程地址,然后才能read

這意味着要么有超時,要么可能是信號中斷了讀取。 您可以在errno.h使用errno的結果來查看錯誤是什么,如果您想在人類可讀的格式化中使用錯誤,可以使用string.h strerror()perror()stdlib.h

更新:根據POSIX規范,您應該在指定SO_RCVTIMEO標志而不是將int轉換為int時將一個struct timeval (在sys/time.h定義)設置為setsockopt超時之前所需的秒數和微秒數一個const char* 因此,即使您的客戶端可能存在錯誤操作並且現在導致不同的錯誤,如果您向函數發送錯誤的參數類型,您仍然可能會遇到問題。

原因在於errno。 可能的場景:

  • [ECONNRESET] d參數引用套接字,並強制關閉遠程套接字端。
  • [EAGAIN]文件被標記為非阻塞I / O,並且沒有數據准備好被讀取。

基本上,您使用以下方法進行非阻塞阻止:

do
{
    read(...);
} while(errno == EAGAIN);

超時時返回-1。

不要設置超時,它將永遠阻塞(好吧,至少在套接字仍然連接時,無論如何)。

我已經解決了這個問題。
感謝您的所有意見,他們給了我很大的幫助。

問題是使用了錯誤的文件描述符

我將服務器套接字的文件描述符傳遞給read() ,而不是傳遞accept()返回的客戶端套接字的文件描述符。

read()可以阻塞,所以如果沒有可用的數據,它將返回-1並將errnoEAGAINEWOULDBLOCK

如果您使用read() ,可以使用select()poll()等待套接字上的數據可用性。

暫無
暫無

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

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