我在Java中使用DataInputStream和DataOutputStream时遇到了一个问题,如果没有一些非常愚蠢的措施我一直无法解决这个问题,并且想知道是否有人知道更好的方法(我非常确定有一个,但我还没有能够找到它) .
背景:我希望能够将Json字符串发送到服务器并让服务器将该字符串解析为对象 . 这需要与语言无关,因为我正在研究的项目需要我有一个异构系统 .
为了显示我的问题的最简单的可能示例,我将排除Gson / Json等的创建,因为它可以使用任何字符串重新创建 . 代码如下:
public class ServerSide {
private final int PORT = 5001;
private ServerSocket servSock;
private Socket sock;
private DataInputStream dis;
private DataOutputStream dos;
public ServerSide() throws IOException {
servSock = new ServerSocket(PORT);
}
public void startListening() {
try {
sock = servSock.accept();
dis = new DataInputStream(sock.getInputStream());
byte[] bytes = new byte[1024];
dis.read(bytes);
String receivedMessage = new String(bytes);
System.out.println("Message received: " + receivedMessage);
sock.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
一个简单的测试类,它创建一个ServerSide()并在一段时间内调用startListening(true) .
public class ClientSide {
private final int PORT = 5001;
private Socket socket;
private DataOutputStream dos;
public ClientSide() {
}
public void sendMessage(String m) {
try {
socket = new Socket("127.0.0.1", PORT);
dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes(m);
System.out.println("Message sent: " + m);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
一个简单的测试类,它创建ClientSide()对象并调用sendMessage(“这是一个测试消息”);
我遇到的问题是我只收到服务器端的部分消息 . 我不确定这是输入或输出流的问题,只能通过多次写入和读取数据并修剪其间的空白来找到解决方法 . 我的第一个问题是当我尝试将Json字符串发送到我在c#中编写的程序时,它会始终发送第一个字符(“{”),然后在下一次读取时发送其余字符串 . 我通过发送一个空格然后在服务器端忽略它来反击这一点 . 当在第一次读取时读取看似随机数量的字符串时,java-java上的问题变得更糟 .
服务器端上述代码的一些示例输出是:
Message received: This is a tes
Message received: T
Message received: T
Message received: T
2 回答
感谢@Illya Kysil提供的帮助我通过将代码更改为:找到了解决方案:
和
这将首先发送一个等于发送消息的字节数组大小的整数 . 可以在服务器端创建具有此长度的缓冲区,并且可以使用DataInputStream的readFully方法来填充此缓冲区 .
is.read(bytes);
may return any number of bytes - 从1到bytes.length
.需要重复调用此方法,直到它返回
-1
,这意味着流结束 .Reading from and Writing to a Socket提供了有关如何读取面向行的交换中的所有数据的示例 . 对于二进制数据(DataStream实际生成的),您需要使用ByteArrayOutputStream,ByteArrayInputStream和DataInputStream的组合:
注意:上面的代码是回答特定问题 . 不要把它投入 生产环境 :)