如何阻止Java套接字客户端持续发送“null”数据?

如何阻止Java套接字客户端持续发送“null”数据?,java,sockets,server,iostream,Java,Sockets,Server,Iostream,我创建了两个带有套接字的Java程序。我希望客户端向服务器发送连续数据。但是在消息发送到服务器之后,客户机继续向服务器发送“null”值,这是在我关闭客户机程序中的套接字时发生的。 这是我的密码: import ... public class MainClient { private Socket serverSock; private PrintStream clientOutput; public static void main(String[] args) {

我创建了两个带有套接字的Java程序。我希望客户端向服务器发送连续数据。但是在消息发送到服务器之后,客户机继续向服务器发送“null”值,这是在我关闭客户机程序中的套接字时发生的。 这是我的密码:

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();
//          }
        }
    }
}
我试图用clientOutput.close关闭客户端的OutputStream;但它在发送0-4循环后向服务器发送空值。 为了使其停止并避免客户端发送空数据,我不应该插入serverSock.close;但它将返回SocketException。我希望客户端在完成后发送“关闭”消息

总之,服务器上的输出是:

Client: 0
Client: 1
Client: 2
Client: 3
Client: 4
Client: null
Client: null
//And so on..
我想客户机程序少了些什么?
谢谢您的帮助:

通常代码应该是类似的

专用主服务器{ 字符串clientMsg=; 试一试{ serverSocket=新的ServerSocketlistenPort; System.out.printlnServer正在侦听+listenPort; clientSocket=serverSocket.accept; clientInput=new BufferedReadernew InputStreamReaderClient socket.getInputStream; 而clientMsg=clientInput.readLine!=null{ ifisTerminationStringclientMsg{ 打破 } System.out.printlnClient:+clientMsg; } }捕捉异常{ 例如,打印跟踪; }最后{ 试一试{ clientSocket.close; }捕捉异常{ } } } 布尔isTerminationStringString msg{ 返回msg.equalstone!; } 如果在isTerminationString中检查消息是否为终止消息,则通信协议应在客户端和服务器之间共享。我举了一个发送的例子 一个已完成的消息,但它可能比这更复杂。
由于关闭套接字上的close方法不能保证其他部分上的套接字也会关闭,因此使用isClosed方法可能无效,并导致与您相同的问题。

您的主客户端没有问题

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循环以及空语句打印。
代码serverSocket.close可帮助您关闭服务器套接字,如果需要停止端口侦听,您可以在“MainServer”上使用此代码。

如注释所述,客户端未发送空值

isConnected方法不会做您认为它会做的事情,也就是说,它不会告诉您套接字当前是否连接到它的对等方,至少不会以您认为应该的方式连接。一旦套接字转换为已连接状态,isConnected将变为true,并且在此后保持true,即使在套接字关闭之后也是如此。请参阅stackoverflow上的和其他

确定对等方是否已关闭连接的正确方法是尝试从套接字读取数据,然后检查结果是否有关闭的迹象。请阅读您正在使用的方法的Javadocs,它们将告诉您各种返回值的含义。对于方法,它说:

返回: 包含行内容的字符串,不包括 任何行终止字符,如果流的结尾有 联系到 抛出: IOException-如果发生I/O错误


因此,您需要检查null返回值以检测正常的套接字关闭,以及是否收到指示某种网络异常的IOException。

readLine循环是正确的,但不需要终止消息。对等方简单地关闭套接字将导致此循环退出。是的,我知道,但您可能需要它以更好地在客户端和服务器之间通信。如何改进?它不会发送“null”数据。请参阅服务器中的Javadoc for readLime.isConnected从不检查客户端的状态。isClosed既不会检测到客户端关闭,也不会在此处“帮助您关闭客户端套接字”。这里没有比断开连接更好的了。很明显你从未试过,我明白了。谢谢你的解释。所以最好使用clientInput.readLine=空条件,如下面解释的答案,以确定对等方已关闭/关闭连接?@motionfrog他已经说过了。这不仅仅是“更好”,它是唯一有效的选择。
       while(!clientSocket.isClosed()) {

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

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