Java 客户端服务器EOF错误
我的应用程序使用DataInputStream和DataOutputStream在服务器和客户端之间进行通信。客户端将从一个网站向我的应用程序发送请求,因此我创建了一个测试客户端来测试可能来自该网站的输入 我决定使用的方法是,客户端首先发送一个整数,决定要发送的数据的大小,然后再发送数据。所以,我在测试这个方法,它对第一个数据字符串有效,但对第二个数据字符串无效,在第二次尝试时给了我一个EOF错误。我理解为什么它给了我一个EOF,因为客户端关闭了连接,但我仍然没有读取传入的字节,所以流应该还有更多的内容可以读取 客户端代码:Java 客户端服务器EOF错误,java,sockets,Java,Sockets,我的应用程序使用DataInputStream和DataOutputStream在服务器和客户端之间进行通信。客户端将从一个网站向我的应用程序发送请求,因此我创建了一个测试客户端来测试可能来自该网站的输入 我决定使用的方法是,客户端首先发送一个整数,决定要发送的数据的大小,然后再发送数据。所以,我在测试这个方法,它对第一个数据字符串有效,但对第二个数据字符串无效,在第二次尝试时给了我一个EOF错误。我理解为什么它给了我一个EOF,因为客户端关闭了连接,但我仍然没有读取传入的字节,所以流应该还有更
Socket socket = new Socket("127.0.0.1", 9000);
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
os.writeInt("Test String".length());
os.write("Test String".getBytes());
os.flush();
os.writeInt("String".length());
os.write("String".getBytes());
os.flush();
os.close();
socket.close();
服务器代码:
byte[] data;
try{
DataInputStream input = new DataInputStream(client.getInputStream());
DataOutputStream output = new DataOutputStream(client.getOutputStream());
client.setSoTimeout(SOCKET_TIMEOUT);
logger.log(Level.INFO, "Client connected with IP: " + client.getInetAddress());
data = readNextPacket(input);
if(!(new String(data).contains(PROTOCOL_HEADER)))
throw new IOException("Invalid request from client.");
else
logger.log(Level.INFO, "Valid header: " + new String(data));
data = readNextPacket(input);
logger.log(Level.INFO, new String(data));
}catch(IOException e){
logger.log(Level.SEVERE, e.getMessage(), e);
}finally{
try {
client.close();
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
logger.log(Level.INFO, "FINISHED");
}
ReadNextPackage方法:
private byte[] readNextPacket(DataInputStream stream) throws IOException{
int bytesToRead = stream.readInt();
ByteArrayOutputStream os = new ByteArrayOutputStream();
if(bytesToRead <= MAX_BYTES){
byte[] data = new byte[bytesToRead];
while(stream.read(data) != -1 && os.size() < bytesToRead){
os.write(data);
}
}
return os.toByteArray();
}
好的,如果第一次没有读取整个缓冲区,那么我的readNextPacket方法将读取比指定的更多的数据。因此,我修改了一些代码,通过向read方法添加一个偏移量并减去我已经读取的量来修复它。但是,我意识到这基本上是复制readFully方法,没有理由这样做,所以我只是将其实现到readNextPacket方法中
以下是新的工作代码:
private byte[] readNextPacket(DataInputStream stream) throws IOException{
int bytesToRead = stream.readInt();
byte[] data = new byte[bytesToRead];
stream.readFully(data);
return data;
}
我建议您使用java.io.ObjectOutputStream.writeObject,而不是先发送长度。。。这里有一个教程:;如果您不想在条件运算符中使用括号,那也没什么错,但这是一个很好的做法。是的,但我不会从Java对象中读取数据,所以我更喜欢使用readInt和writeInt,因为它们只是将读取的前四个字节转换为int。但是,在我的应用程序中,这似乎不是问题,也不应该是问题。您在ReadNextPackage中编写的代码不正确,但我建议您使用writeUTF编写字符串,并使用readUTF读取字符串,而不是手动复制它们的功能,不正确。实际上writeUTF和readUTF使用的协议与我使用的完全不同。我的方法要简单得多,我更喜欢与网站交流。为什么它不正确呢@EJP@EJP您是对的,如果不成功,我将进行另一次读取,但我将第一次读取的内容放入ByteArrayOutputStream,并使用它来计算我已读取的字节数,因此我不会丢失任何字节。我也不使用API方法,因为编写客户机的人不会使用Java,而是更喜欢我使用的方法?如果失败,除了长单词之外,你什么都不读,而是静默地读,下面对这个方法的调用将以奇怪的方式失败。最好是不管发生什么都让它发生,并立即失败,而不是为以后的调试制造噩梦。
private byte[] readNextPacket(DataInputStream stream) throws IOException{
int bytesToRead = stream.readInt();
byte[] data = new byte[bytesToRead];
stream.readFully(data);
return data;
}