我正在學習 java 中的套接字,但是當我運行一個從客戶端向服務器端發送訊息的程式時,它沒有顯示訊息。如果我在客戶端輸入一些文本,它不會顯示在服務器端,但如果我輸入 endProcess 它會停止運行。這意味著訊息正在通過它只是沒有顯示出來。
我的 Client.java 代碼在這里:
import java.net.*;
import java.io.*;
public class Client{
Socket soc;
DataInputStream dis;
DataOutputStream dos;
public Client(){
try{
soc = new Socket("(Address)",5000);
System.out.println("Connection Established");
dis = new DataInputStream(System.in);
dos = new DataOutputStream(soc.getOutputStream());
System.out.println("Streams connected");
}catch(UnknownHostException u){
System.out.println(u);
}catch(IOException i){
System.out.println(i);
}
String line = "";
while(!line.equals("endConnection")){
try{
line = dis.readUTF();
dos.writeUTF(line);
}catch(IOException i){
System.out.println(i);
}
}
try {
soc.close();
dis.close();
dos.close();
} catch (Exception e) {
System.out.println(e)
}
}
public static void main(String[] args) {
new Client();
}
}
這是我的 Server.java 代碼:
import java.net.*;
import java.io.*;
public class Server {
ServerSocket serSoc;
Socket soc;
DataInputStream dis;
public Server(){
try {
serSoc = new ServerSocket(5000);
System.out.println("Server Online");
soc = serSoc.accept();
System.out.println("Client Connected");
dis = new DataInputStream(new BufferedInputStream(soc.getInputStream()));
String line = "";
System.out.println("Waiting for input...");
while(!line.equals("endConnection")){
line = dis.readUTF();
System.out.println(line);
}
System.out.println("Client disconnected");
soc.close();
dis.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
new Server();
}
}
uj5u.com熱心網友回復:
這里有很多問題。
雙工協議問題
line = dis.readUTF(); dos.writeUTF(line);
這是行不通的;在讀取一行之前,該行將dis.readUTF()被阻塞(凍結)。問題是,有時在您想閱讀的情況下您沒有什么可發送的,而在您想發送的情況下您沒有什么可閱讀的。在實踐中,您需要完全重新設計它;你需要2個執行緒。此時您會遇到多核問題,需要同步原語和/或java.util.concurrent類,以便在 2 個執行緒之間共享的所有資料。
或者,采用嚴格推或拉的模型(在任何給定時間,雙方都知道誰可以發送,如果對方想要發送,他們根本就不能發送。例如,每一方都發送一個簡單的“NOTHING TO DO”每秒訊息,每次交換位置。當然,這是一個效率很低的演算法。但是可以在不涉及多個執行緒的情況下撰寫。
重繪 和關閉問題
dos.writeUTF(line);
這實際上并沒有發送任何東西,或者至少不能保證發送任何東西。要在互聯網上發送任何資料,它會被包裝在一個具有大量開銷的資料包中。所以,事情會被緩沖,直到有一個完整的資料包要發送。這意味著該行不執行任何操作。它只是填充一個緩沖區,沒有資料包出去。您首先需要關閉或沖洗。dos.flush()也許會有所幫助。這是一個大問題,因為稍后你會這樣做:
soc.close(); dis.close(); dos.close();
您首先關閉套接字,然后關閉套接字。然后關閉流,這也將發送仍然卡在緩沖區中的任何內容,但由于套接字已經關閉,這將失敗。換句話說,你.writeUTF()-ed 的那一行?它永遠不會到達那里。您首先將其推入緩沖區,然后關閉套接字,然后發送緩沖區,由于套接字已經關閉,該緩沖區將不起作用。
中斷錯誤處理
} catch (Exception e) { System.out.println(e); }
可怕。不要這樣做。您的代碼通過列印某些內容并繼續運行來對任何問題做出反應。這意味著如果出現任何問題,客戶端將開始向無休止的例外跟蹤行列發送垃圾郵件并鎖定系統,如果運氣好的話。您希望代碼在出現問題時停止運行。到目前為止,最簡單的方法就是堅持throws IOException使用您的建構式和 main 方法,這是允許的。遙遠的第二個最佳選擇是將您的“ehwhatever”捕獲塊配置為throw new RuntimeException("unhandled", e);而不是e.printStackTrace().
你所做的 ( System.out.println(e);)更糟糕- 你正在丟棄非常有用的資訊,例如堆疊跟蹤和因果鏈。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/475868.html
上一篇:具有多個套接字的UDP網路
下一篇:TCP發送緩沖區沒有做任何事情
