[英]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
設置為EAGAIN
或EWOULDBLOCK
。
如果您不想要非阻塞行為,為什么要將套接字設置為非阻塞?
編輯:格爾,你已經改變了你的問題。 ENOTCONN
的原因是您嘗試從未連接的套接字讀取。 除非通過accept
或socketpair
獲得套接字,否則必須在其上調用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
並將errno
為EAGAIN
或EWOULDBLOCK
。
如果您使用read()
,可以使用select()
或poll()
等待套接字上的數據可用性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.