Java socket 读取后立即写入
Posted
技术标签:
【中文标题】Java socket 读取后立即写入【英文标题】:Java socket write immediately after read 【发布时间】:2018-03-22 10:58:11 【问题描述】:基本上,我想要实现的是完成客户端套接字和服务器套接字之间的乒乓通信。
场景应该是这样的:
-
客户端建立与服务器的连接。
客户端发送“Hello”到服务器(通过OutputStream),然后开始从服务器读取(通过InputStream)
服务器读取“Hello”消息并打印到控制台,然后将“Hello”发送到客户端(通过 OutputSteam)。
客户端打印来自服务器的响应消息并退出。
服务器套接字:
try (ServerSocket serverSocket = new ServerSocket(8080))
while (true)
// Blocking here
Socket socket = serverSocket.accept();
InputStream inStream = socket.getInputStream();
OutputStream outStream = socket.getOutputStream();
String reqMessage = new String(inStream.readAllBytes(), StandardCharsets.UTF_8);
System.out.println(reqMessage);
String resMessage = "Hello";
outStream.write(resMessage.getBytes(StandardCharsets.UTF_8));
outStream.flush();
System.out.println(String.format("Message '%s' has been sent to client", resMessage));
outStream.close();
socket.close();
客户端套接字:
Socket socket = new Socket("localhost", 8080);
OutputStream outStream = socket.getOutputStream();
outStream.write("Hello Server".getBytes(StandardCharsets.UTF_8));
outStream.flush();
InputStream inStream = socket.getInputStream();
System.out.println("Received from server");
System.out.println(new String(inStream.readAllBytes(), StandardCharsets.UTF_8));
outStream.close();
socket.close();
我的问题:
一旦建立连接,双方都被阻塞,没有人打印正确的消息,就像他们在等待对方一样。一旦我关闭客户端,服务器就会打印所有正确的信息。但是,如果我从客户端删除了“从服务器读取”部分,即 InputStream 部分,那么双方都可以正常工作。我只是感到困惑,为什么它会这样?如果我想让它工作,我应该修改什么?
谢谢。
【问题讨论】:
你研究过NIO非阻塞socket***.com/questions/11745686/java-nio-client/… 您的问题是什么,您是否尝试在服务器中第二次调用inStream.readAllBytes()
以确保返回一个空数组(= 流标记结束)。如果在客户端关闭套接字之前从未调用过第二次调用,则在网络套接字流中无法识别 EOF 对这个函数有用。您可以定义消息格式numOfBytes(64bit),databytes
并在您的服务器和客户端中相应地读取。不要等待真正的文件结束/流结束状态。
@Whome 是的,但我只是在热身并练习一些基本概念,我认为 Kayaman 给出了正确答案,所有问题都来自readAllBytes()
,它一直等到流关闭,这将永远不会发生。
【参考方案1】:
您的问题在于readAllBytes()
。这并不意味着它会读取所有可用的字节,它会读取所有字节,直到流关闭。
String reqMessage = new String(inStream.readAllBytes(), StandardCharsets.UTF_8);
将阻塞直到您关闭客户端,因为服务器仍在等待“所有”字节。同时客户端正在等待服务器发送一些东西,当然它不能这样做,因为它仍在等待来自客户端的更多数据。
无论如何,您都不应该使用字节,因为您正在编写文本消息。使用BufferedReader
和InputStreamReader
,例如PrintWriter
和OutputStreamWriter
来编写文本。不要忘记readLine()
需要来自发件人的换行符,并在InputStreamReader
和OutputStreamWriter
中指定字符编码。
【讨论】:
以上是关于Java socket 读取后立即写入的主要内容,如果未能解决你的问题,请参考以下文章
actionscript socket readBytes() <- java app write() write() write()