簡體   English   中英

如何停止Java Socket客戶端不斷發送“空”數據?

[英]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.

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