簡體   English   中英

java套接字/輸出流寫入:它們阻塞嗎?

[英]java socket / output stream writes : do they block?

如果我只在輸出流上寫入套接字,它會阻塞嗎? 只有讀取可以阻塞,對嗎? 有人告訴我寫可以阻塞,但我只看到套接字讀取方法的超時功能 - Socket.setSoTimeout()

對我來說,寫可能會阻塞是沒有意義的。

對 Socket 的寫入也可能會阻塞,尤其是在它是 TCP Socket 的情況下。 操作系統只會緩沖一定數量的未傳輸(或傳輸但未確認)的數據。 如果你寫東西的速度比遠程應用程序讀取的速度快,套接字最終會備份,你的write調用將阻塞。

回答這些后續問題:

那么有沒有一種機制可以為此設置超時? 我不確定它會有什么行為......如果緩沖區已滿,可能會丟棄數據? 或者可能刪除緩沖區中的舊數據?

沒有在 java.net.Socket 上設置寫入超時的機制。 有一個Socket.setSoTimeout()方法,但它影響accept()read()調用......而不是write()調用。 顯然,如果您使用 NIO、非阻塞模式和 Selector,您可以獲得寫入超時,但這並不像您想象的那么有用。

除非連接關閉,否則正確實現的 TCP 堆棧不會丟棄緩沖的數據。 但是,當您收到寫入超時時,不確定當前位於操作系統級緩沖區中的數據是否已被另一端接收...... 另一個問題是您不知道上次write的數據中有多少實際傳輸到了操作系統級別的 TCP 堆棧緩沖區。 缺少一些用於重新同步流*的應用程序級協議,在write超時后唯一安全的做法是關閉連接。

相比之下,如果您使用 UDP 套接字,則write()調用不會阻塞很長時間。 但不利的一面是,如果出現網絡問題或遠程應用程序跟不上,消息將被丟棄在地板上,而不會通知任何一方。 此外,您可能會發現消息有時會亂序傳遞到遠程應用程序。 由您(開發人員)來處理這些問題。

* 理論上可以做到這一點,但對於大多數應用程序來說,在已經可靠(到一定程度)的 TCP/IP 流之上實現額外的重新同步機制是沒有意義的。 如果它確實有意義,您還需要處理連接關閉的可能性......所以假設它關閉會更簡單。

這樣做的唯一方法是使用 NIO 和選擇器。

請參閱此錯誤報告中來自 Sun/Oracle 工程師的文章: https ://bugs.java.com/bugdatabase/view_bug.do?bug_id=4031100

暫無
暫無

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

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