[英]manage socket connection in Java over tcp
我寫了一個客戶端,基本上只打開一個套接字並通過連接發送內容。 (內容遵循Http協議)
我所面臨的問題與該問題有關-我應如何以及何時關閉連接。 問題是連接有時關閉得太早(服務器應答之前,“ FIN”已發送到服務器)。
在這種情況下,服務器的答案將丟失。
我嘗試在關閉連接之前使用Thread.sleep,但似乎沒有任何影響到內容發送和“ FIN”消息發送之間的時間。 (在Wireshark中查看)
答案有時到來,有時卻沒有(比賽條件)。
我該如何延遲“ FIN”消息,以免錯過服務器的響應?
我添加了相關的課程。 相關功能是sendContentOverSocket
public class SocketClient {
private String hostName;
private int portNumber;
private Socket ConnectionSocket;
public void init(String hostName, int portNumber){
this.hostName = hostName;
this.portNumber = portNumber;
this.ConnectionSocket=createSocketConnection();
}
private Socket createSocketConnection() {
Socket socket = null;
try {
socket = new Socket(this.hostName, this.portNumber);
return socket;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
public void sendContentOverSocket(String content) {
try {
PrintWriter out = new PrintWriter(
ConnectionSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
ConnectionSocket.getInputStream()));
out.print(content);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.close();
in.close();
ConnectionSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP使用稱為半封閉的概念。 當您關閉套接字時,這表示您將不再發送。 在您的解釋中,我看到“在服務器應答之前先將FIN發送到服務器”,如果您是客戶端,則意味着您已對套接字執行了關閉操作。 如果您希望服務器在特定時間內得到結果,則需要某種計時機制,可能將select與超時結合使用。 如果服務器關閉其連接的末端,則可以通過接收receive中的字節來檢測到這一點。 通常,這意味着您也必須關閉插座。 因此,總而言之,有3個原因可以關閉插座:
當然,您應該在閱讀響應后關閉連接。 很難在這里看到這個謎。 沒睡 如果您不閱讀響應(a)您將無法知道請求是成功還是失敗,以及(b)服務器也有可能遇到異常。
您的代碼質量很差。 所有這些方法都應傳播異常,而不是在內部捕獲異常並返回null。
對於Java 7,由於所有三個類(即Socket , PrintWriter , BufferedReader )都實現AutoCloseable,並且基於這樣的事實,您想在調用sendContentOverSocket(String content)
之后立即關閉套接字,請嘗試使用以下代碼:
public class SocketClient {
private String hostName;
private int portNumber;
public void init(String hostName, int portNumber) {
this.hostName = hostName;
this.portNumber = portNumber;
}
public void sendContentOverSocket(String content) {
try (Socket socket = new Socket(this.hostName, this.portNumber);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
out.print(content);
} catch(IOException e) {
//Appropriate exception handler
}
}
}
在這種情況下,Java將自行正確關閉所有資源。
如果您使用Java 6或更早版本,請嘗試使用try-finally塊代替:
解決了。
我現在了解它是如何工作的。 我在客戶端中缺少的是嘗試從輸入Stream讀取的內容。 當您嘗試閱讀時
while ((inputFromServer = in.readLine()) != null)
客戶端等待輸入。 唯一會打破此循環的是服務器關閉連接。
之后,您可以安全地在客戶端上關閉連接。 無需延遲FIN等
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.