簡體   English   中英

使用Java接收時TCP套接字掛起

[英]TCP Socket Hangs while receiving in Java

我在Java應用程序中使用TCP套接字。 我正在嘗試使用readInt()方法從某些設備接收字節數據。

如果我從設備獲取4個字節,則此方法可以正常工作。 但是,如果我得到的少於4個字節或什么都沒有,則readInt()掛起。 它被阻止,不會返回。 如果沒有要接收的數據,則應該拋出EOFException異常,但是它正在掛起。

碼:

DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream   din = new DataInputStream(socket.getInputStream());

int res = din.readInt();

在套接字關閉之前,不會引發EOFException

當您嘗試讀取的數據多於可用數據時,此方法應會阻塞。 它僅在套接字關閉時才返回EOFException,因為這是實際的EOF條件。 如果套接字保持打開狀態,它將阻塞直到它有足夠的數據來填充請求。

這是套接字工作方式的基本本質的一部分。 要使Java的行為有所不同,就必須錯誤地實現套接字行為。

將套接字協議放在一起時,應該考慮這一點。 為什么要等待一個int被接收並且僅發送int的一部分? 這永遠都不會發生。 如果要發送不同類型的數據,則應首先包含某種報頭字節,以告知接收器接下來要接收哪種數據,以便知道如何處理數據以及如何處理數據。

僅當連接的另一端關閉套接字時才會拋出該異常。 否則,接收方沒有任何跡象表明將不再有數據,因此它將等待(調用readInt時,您告訴它至少要獲取四個字節)。 您將必須讀取字節並將其自己解析為應用程序塊。

您正在使用的類構成了執行阻塞 I / O的java.io包的一部分。 正確的解決方案是切換到使用java.nio定義的非阻塞I / O類。 請注意,編寫非阻塞I / O應用程序並非易事。 但是,這是避免I / O線程可能無限期阻塞的唯一解決方案。

請注意,作為一種駭人聽聞的解決方案,您可以使用專用的阻塞I / O線程,該線程僅讀取並向另一個線程輪詢的BlockingQueue添加字節。 使用者線程可以使用相當長的超時值在BlockingQueue上調用poll(long, TimeUnit) ,如果調用返回null則可以認為這意味着沒有更多數據可用。 請注意,這是一個非常丑陋的解決方案,因為這意味着您的I / O“生產者”線程將在此時保持阻塞狀態。

僅當您錯誤地實施了應用程序協議時,才會出現這種情況。 您為什么期望一個4字節的整數,而應用程序僅發送1-3個字節? 它真的發送二進制int嗎? 還是應該閱讀並解析ASCII字符串?

暫無
暫無

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

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