java - 如何从 TCP 服务器向 TCP 客户端发送回复?

标签 java sockets tcp

我有以下服务器和客户端代码。客户端能够成功向服务器发送数据,但是当客户端尝试从服务器读取数据时,代码继续运行,没有任何输出。

服务器:

public static void main(String[] args) throws Exception {

    ServerSocket s = new ServerSocket(9898);

    while(true) {

        Socket recv = s.accept();

        InputStream inp = recv.getInputStream();
        OutputStream out = recv.getOutputStream();

        String data = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(inp));
        while ( (data = in.readLine()) != null ) {
            System.out.println("\r" + data);
        }

        out.write("sampleSendToClient".getBytes());
    }

}

客户:

public static void main(String[] args) throws Exception{
    Socket clientSocket = new Socket("localhost", 9898);
    OutputStream out = clientSocket.getOutputStream();
    InputStream inp = clientSocket.getInputStream();

    out.write("sampleSendToServer".getBytes());

    String data = null;
    //if I dont write next 4 lines then client exits gracefully 
    //but now it is stuck infinitely
    BufferedReader in = new BufferedReader(new InputStreamReader(inp));
    while ( (data = in.readLine()) != null ) {
        System.out.println("\r" + data);
    }

    clientSocket.close();
}

我无法理解上面的代码有什么问题。

最佳答案

快速而轻松地,您的服务器通过调用 OutputStream#write(byte[] data) 直接在输出流上写入,但您的客户端使用 BufferedReader 进行读取BufferedReader#readLine() 是一个阻塞 I/O 操作,它将挂起线程直到出现 \n\r 字符到达InputStream(或者流被关闭,在这种情况下,方法被中断,返回null)。

您的服务器发送的字符串不以 \n\r 结尾,因此数据可能已经发送并停留在客户端 的缓冲区中BufferedReader 但没有任何一个终止字符 readLine() 将永远不会返回。

简单地改变

out.write("sampleSendToClient".getBytes());

out.write("sampleSendToClient\n".getBytes());

应该可以解决问题。

更新:

while ( (data = in.readLine()) != null ) {
        System.out.println(data);
    }

只有当readLine()返回null时,这个while循环才会退出,只有当流被关闭时才会出现这种情况。但是,由于您无法在不丢失连接的情况下关闭流,因此您必须找到另一种方法来终止循环,因为现在它将永远运行。

即使添加了\n,你的服务器也不会响应,因为此时他将无限循环。

<小时/>

旁注:对于每个新连接,您都会覆盖以前的套接字而不关闭其资源(主要集中在数据流和套接字本身),因此会造成资源泄漏。考虑在不再需要时关闭每个对象。

关于java - 如何从 TCP 服务器向 TCP 客户端发送回复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50701331/

相关文章:

sockets - Flutter:如何作为 tcp 客户端发送包

java - 搜索子集(有趣的复杂任务)

java - 连接到 CouchDB 时强制设置连接超时

java - 访问 Java 异常对象的详细消息

c - memcpy: unix socket sun_path 起始地址索引

sockets - 来自特定网卡的 UDP 组播

c++ - C++中的TCP重传超时检测

c# - 如何在多线程 C# 中使用 TCP 客户端/监听器?

java - 是否有与嵌套类关联的构造函数

c - 使用 EOF 多路复用非阻塞套接字 IO