[英]How to stop Java Socket client keeps sending 'null' data?
我創建了2個帶有套接字的Java程序。 我希望客戶端將連續數據發送到服務器。 但是在消息發送到服務器后,客戶端繼續向服務器發送“空”值(在我關閉客戶端程序中的套接字時會發生這種情況)。 這是我的代碼:
import ...
public class MainClient {
private Socket serverSock;
private PrintStream clientOutput;
public static void main(String[] args) {
MainClient client = new MainClient();
client.runClient();
}
public void runClient() {
try {
serverSock = new Socket("127.0.0.1",8282);
clientOutput = new PrintStream(serverSock.getOutputStream());
clientOutput.println("Hello, I'm Connected.");
for (int i=0;i<5;i++) {
clientOutput.println(i + "");
clientOutput.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// try {
// serverSock.close(); It will keeps sending 'null' data to the server if I use this line.
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}
服務器端:
public class MainServer {
private ServerSocket serverSocket;
private int listenPort = 8282;
private InputStream inps;
private Socket clientSocket;
private BufferedReader clientInput;
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(clientSocket.isConnected()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
}
}catch(IOException ex) {
ex.printStackTrace();
}finally {
try {
clientSocket.close();
} catch (IOException e) {}
}
}
public static void main(String[] args) {
new MainServer();
}
}
我試圖用clientOutput.close();
關閉客戶端的OutputStream clientOutput.close();
但在發送0-4循環后,它將向服務器發送null。 為了使其停止並避免客戶端發送空數據,我不應該插入serverSock.close();
在客戶端上,但是它將返回SocketException。 我希望客戶端在完成后發送“已關閉”消息。
總結,服務器上的輸出是:
Client: 0
Client: 1
Client: 2
Client: 3
Client: 4
Client: null
Client: null
//And so on..
我認為客戶程序中缺少某些內容,我猜呢? 感謝您的幫助 :)
正如評論所指出的,客戶端沒有發送null
值。
該isConnected()
方法不會做你認為它,即它不會告訴你,如果該套接字當前在你認為它應該的方式“連接”到它的同行,至少。 一旦套接字轉換為已連接狀態, isConnected()
就會變為true,此后甚至在套接字關閉后也保持為true。 請參閱此討論以及有關stackoverflow的其他討論 。
確定對等方是否已關閉連接的正確方法是嘗試從套接字讀取,然后檢查結果以查找關閉的證據。 請閱讀您使用的方法的Javadocs,它們會告訴您各種返回值的含義。 對於BufferedReader.readLine()
方法,它表示:
返回值:
一個字符串,其中包含行的內容,不包含任何行終止符;如果已到達流的末尾,則為null
拋出:
IOException-如果發生I / O錯誤
因此,您需要檢查返回的空值以檢測正常的套接字關閉,以及是否收到指示某種網絡異常的IOException。
您的MainClient()沒問題。
MainServer()中的clientSocket.isConnected()函數始終檢查客戶端的狀態,並導致無限循環,因此在消息“ client:4”之后,clientInput.readLine()應該返回“ null”。
因此,您可以使用函數“ clientSocket.isClosed()”來檢查客戶端套接字是否已關閉,而不是檢查客戶端套接字是否已連接。
用下面的代碼替換MainServer()中的while循環,
while(!clientSocket.isClosed()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
if(clientMsg.equals("Closed")){
clientSocket.close();
// serverSocket.close();
}
}
這將幫助您在收到來自服務器的“ Closed”消息時關閉客戶端套接字,從而避免了while循環的無限執行以及null語句的打印。 代碼“ serverSocket.close()”可幫助您關閉服務器套接字,如果需要停止端口監聽,則可以在“ MainServer()”中使用它。
通常,代碼應該是類似的東西
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((clientMsg = clientInput.readLine()) != null) {
if(isTerminationString(clientMsg)) {
break;
}
System.out.println("Client : " + clientMsg);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
}
}
}
boolean isTerminationString(String msg) {
return msg.equals("DONE!");
}
在isTerminationString
,如果您檢查msg是否是終止msg,則應在客戶端和服務器之間共享通信協議。 我以發送DONE消息為例,但是它可能比這更復雜。 因為在套接字上關閉close
方法不能保證另一部分上的套接字也被關閉,所以使用isClosed
方法可能無效,並且會導致您遇到相同的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.