简体   繁体   English

如何停止Java Socket客户端不断发送“空”数据?

[英]How to stop Java Socket client keeps sending 'null' data?

I created 2 Java programs with sockets in it. 我创建了2个带有套接字的Java程序。 I want the client to send continuous data to the server. 我希望客户端将连续数据发送到服务器。 But after the message sent to the server, the client keeps sending 'null' value to the server (it happens when I close the socket in client program). 但是在消息发送到服务器后,客户端继续向服务器发送“空”值(在我关闭客户端程序中的套接字时会发生这种情况)。 Here is my codes: 这是我的代码:

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();
//          }
        }
    }
}

The Server Side: 服务器端:

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();
    }
}

I tried to close the OutputStream on the Client side with clientOutput.close(); 我试图用clientOutput.close();关闭客户端的OutputStream clientOutput.close(); but it sends nulls to the server after it sends the 0-4 loop. 但在发送0-4循环后,它将向服务器发送null。 To make it stop and avoid the client sends null data, i should not insert the serverSock.close(); 为了使其停止并避免客户端发送空数据,我不应该插入serverSock.close(); on the Client, but it will returns SocketException. 在客户端上,但是它将返回SocketException。 I wanted the client to send 'Closed' message after its done. 我希望客户端在完成后发送“已关闭”消息。

Summary, the output on the server is: 总结,服务器上的输出是:

Client: 0
Client: 1
Client: 2
Client: 3
Client: 4
Client: null
Client: null
//And so on..

I think there is something missing on the Client Program, i guess? 我认为客户程序中缺少某些内容,我猜呢? Thank you for the help :) 感谢您的帮助 :)

As the comment noted, the client is not sending a null value. 正如评论所指出的,客户端没有发送null值。

The isConnected() method does not do what you think it does, namely it does not tell you if the socket is currently "connected" to its peer, at least in the way you think it should. isConnected()方法不会做你认为它,即它不会告诉你,如果该套接字当前在你认为它应该的方式“连接”到它的同行,至少。 isConnected() becomes true as soon as the socket transitions into the connected state, and stays true thereafter, even after the socket is shutdown. 一旦套接字转换为已连接状态, isConnected()就会变为true,此后甚至在套接字关闭后也保持为true。 See this discussion and others on stackoverflow. 请参阅此讨论以及有关stackoverflow的其他讨论

The correct way to determine if the peer has shutdown the connection is to attempt to read from the socket and then examine the result for evidence of closure. 确定对等方是否已关闭连接的正确方法是尝试从套接字读取,然后检查结果以查找关闭的证据。 Please read the Javadocs for the method you are using, they will tell you what the various return values mean. 请阅读您使用的方法的Javadocs,它们会告诉您各种返回值的含义。 For the BufferedReader.readLine() method, it says: 对于BufferedReader.readLine()方法,它表示:

Returns: 返回值:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached 一个字符串,其中包含行的内容,不包含任何行终止符;如果已到达流的末尾,则为null
Throws: 抛出:
IOException - If an I/O error occurs IOException-如果发生I / O错误

Thus you need to check for a null return value to detect a normal socket closure, and if you receive an IOException that indicates some kind of network anomaly. 因此,您需要检查返回的空值以检测正常的套接字关闭,以及是否收到指示某种网络异常的IOException。

Your MainClient() have no problem. 您的MainClient()没问题。

clientSocket.isConnected() function in MainServer() always check the status of the client and which results an infinite loop, so after the message 'client:4', clientInput.readLine() should return 'null'. MainServer()中的clientSocket.isConnected()函数始终检查客户端的状态,并导致无限循环,因此在消息“ client:4”之后,clientInput.readLine()应该返回“ null”。

So instead of checking the client socket is connected or not you can check the client socket is closed or not using function 'clientSocket.isClosed()'. 因此,您可以使用函数“ clientSocket.isClosed()”来检查客户端套接字是否已关闭,而不是检查客户端套接字是否已连接。

replace the while loop in MainServer() with below code, 用下面的代码替换MainServer()中的while循环,

       while(!clientSocket.isClosed()) {

                clientMsg = clientInput.readLine();
                System.out.println("Client : " + clientMsg);

                if(clientMsg.equals("Closed")){
                     clientSocket.close();
                //  serverSocket.close();
                }
            }

this will help you to close the client socket at the time of receiving 'Closed' message from server and this avoid the infinite execution of while loop as well as null statement printing. 这将帮助您在收到来自服务器的“ Closed”消息时关闭客户端套接字,从而避免了while循环的无限执行以及null语句的打印。 The code "serverSocket.close()" help you to close the server socket and you can use this at 'MainServer()' if you need to stop the port listening. 代码“ serverSocket.close()”可帮助您关闭服务器套接字,如果需要停止端口监听,则可以在“ MainServer()”中使用它。

typically the code should be something similar 通常,代码应该是类似的东西

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!");
}

where in isTerminationString you check if the msg is a termination msg, the communication protocol should be shared between the client and the server . isTerminationString ,如果您检查msg是否是终止msg,则应在客户端和服务器之间共享通信协议。 i gave the example of sending a DONE message, but it could more complex than that . 我以发送DONE消息为例,但是它可能比这更复杂。 as closing the close method on the socket does not guarantee that the socket on the other part gets closed as well, using the isClosed method might not be effective and results in the same problem you have . 因为在套接字上关闭close方法不能保证另一部分上的套接字也被关闭,所以使用isClosed方法可能无效,并且会导致您遇到相同的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM