当前位置: 首页 > 知识库问答 >
问题:

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

韩祯
2023-03-14

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

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

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

我想客户程序中缺少了一些东西,我想?谢谢你的帮助:)


共有3个答案

白博易
2023-03-14

通常代码应该是类似的

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中检查消息是否为终止消息时,客户端和服务器之间应共享通信协议。我举了一个发送已完成消息的例子,但它可能比这更复杂。由于关闭套接字上的close方法并不能保证另一部分的套接字也会关闭,因此使用isClosed方法可能无效,并会导致与您相同的问题。

冀景明
2023-03-14

您的MainClient()没有问题。

clientSocket。MainServer()中的isConnected()函数始终检查客户端的状态,这会导致无限循环,因此在消息“client:4”后,clientInput。readLine()应返回“null”。

因此,不必检查客户端套接字是否已连接,您可以检查客户端套接字是否已关闭或未使用函数“clientSocket”。isClosed()。

用下面的代码替换MainServer()中的同时循环,

       while(!clientSocket.isClosed()) {

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

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

这将帮助您在从服务器接收“Closed”消息时关闭客户端套接字,从而避免无限执行while循环以及空语句打印。代码“serverSocket.close()”帮助您关闭服务器套接字,如果需要停止端口侦听,可以在“MainServer()”中使用该代码。

段干宾白
2023-03-14

正如评论所指出的,客户端没有发送null值。

isConnected()isConnected()在套接字转换为已连接状态后立即变为true,并在此后保持true,即使在套接字关闭后也是如此。请参阅此讨论和stackoverflow上的其他讨论。

确定对等方是否已经关闭连接的正确方法是尝试从套接字中读取,然后检查结果以寻找关闭的证据。请阅读您正在使用的方法的Javadocs,它们会告诉您各种返回值的含义。对于BufferedReader.readLine()方法,它说:

返回:
一个包含行内容的字符串,不包括任何行终止字符,如果已到达流的结尾,则返回null;
抛出:
IOException-如果发生I/O错误

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

 类似资料:
  • 我有一个关于Java插座的技术问题。 例如,假设我有一个Java Sockets服务器和n个多个客户端。是否可以几乎实时地将数据从服务器发送到任何或所有客户端? 更准确地说: 有哪种监听器可以在Sockets客户端中实现 有人能告诉我什么方法是最好的吗?此外,如果有人有一个代码示例,我也会很高兴。 谢谢

  • 我也试图从Java服务器和Python客户机传输数据。我成功地将数据从客户端传输到服务器,但根本没有接收到数据。 在python客户机上,我有以下内容:(注意,这是在一个单独的线程中运行的) 如果这是成功的工作,输出将是客户端套接字值,等待服务器,然后得到一些数据。然而,它正陷入等待数据的困境。 这意味着套接字显然不是None,它正在等待缓冲区接收?我将接收缓冲区大小设置为1,以查看是否有任何数据

  • 我正在做一个正在改造/现代化的项目,其中有一个小的RMI部分,不幸的是,我以前从未与RMI合作过。 我不明白的一件事是,为什么在我最初创建RMI客户端之后,它一直调用其自定义SocketFactory构造函数。似乎每5分钟我就会看到一次调用构造函数的输出,即使客户端和服务器之间没有通信。 连接完成后,我应该做什么来清理和停止任何线程以进行持久化? 我在检查UnicastRemoteObject,也

  • 我正试图从套接字服务器(Java)向套接字客户端(Python)发送一个映像,但客户端中接收到的映像大小不正确,无法打开。我不知道我做错了什么。有什么建议吗?

  • 我希望能够连接到需要智能卡的个人证书进行身份验证的https站点。我想我已经很接近让它工作了,但不知道如何克服这个例外: 由于合同关系,我不能共享我的代码,但这里有一个总结: 我创建了一个密钥库,其中包含从浏览器导出的所有证书。我使用此密钥存储作为SSLContext的信任存储。我非常肯定这个密钥库包含正确的CA证书来验证远程站点的证书,因为它修复了“无法找到请求目标的有效证书路径”的异常。 我可