我从以下代码中获取EOFException
:
if (!(in.read() == -1))
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
bw.write(canData.toString());
}
else
{
System.out.println("in.read() == -1 "+in.readObject());
jLab0x28.setText("No more bytes to read ");
}
我正在进行Socket编程,其中服务器以某种间隔向客户端发送连续数据。通过套接字从服务器传递到客户端的数据是我开发的CANDataInfo对象类型。在客户端,当我打印数据时,我得到例外。由于对象的读取始终为-1,因此我无法在某个文件上记录数据。
服务器端代码:
private ServerSocket server = null;
private Socket client = null;
private ObjectOutputStream out;
public static final String TAG = "APP1";
private void structureData(CANDataInfo canDataInfo)
{
try
{
if(server == null)
{
server = new ServerSocket(38301);
server.setSoTimeout(0);
}
client = server.accept();
Log.e("Server ", ""+client.isConnected());
Log.e("Data ", ""+canDataInfo.toString());
if(!client.isConnected())
{
Log.e("Server ", "client.isConnected() "+client.isConnected());
server.close();
}
out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(canDataInfo);
out.close();
}
catch (Exception ex)
{
Log.e(CANManagerSetUp.TAG, "" + ex);
}
}
客户端代码 {不是一个干净的解决方案,请参阅EJP的答案}
package com.cnh.socket.client;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import javax.swing.JLabel;
import cantest.setup.CANDataInfo;
public class ThreadListener
{
Socket client = null;
ObjectInputStream in = null;
ListenFor0X28 runnableListenFor0X28 = null;
boolean continueMe;
public class ListenFor0X28 implements Runnable
{
JLabel jLab0x28;
public ListenFor0X28(){}
public ListenFor0X28(boolean stop, JLabel jLab0x28)
{
continueMe = stop;
this.jLab0x28 = jLab0x28;
}
public void run()
{
while(continueMe)
{
try
{
client = new Socket("localhost", 38301);
in = new ObjectInputStream(client.getInputStream());
if(client.isConnected())
{
jLab0x28.setText("Connected to Server");
appendFile(continueMe, jLab0x28, client);
}
else
{
System.out.println("Client is trying to connect");
jLab0x28.setText("Client is trying to connect");
}
}
catch(Exception ex)
{
ex.printStackTrace();
System.err.println("Before Append "+ex.toString());
}
}
}
}
BufferedWriter file = getFile("C:\\ISSUE124_Resolved.txt");
private void appendFile(boolean continueMe, JLabel jLab0x28, Socket client)
{
try
{
if(!client.isClosed())
{
try
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
file.write(canData.toString());
file.flush();
}
catch (EOFException exp)
{
continueMe = true;
System.out.println("A Stream has finished "+exp.toString()+"\n");
}
catch (ClassNotFoundException exp)
{
exp.printStackTrace();
System.err.println(exp.toString());
continueMe = false;
}
}
if(!continueMe)
{
file.close();
client.close();
in.close();
jLab0x28.setText("Socket is closed "+client.isClosed());
}
}
catch(IOException exp)
{
exp.printStackTrace();
System.err.println("Exception "+exp.toString());
jLab0x28.setText(exp.getMessage());
continueMe = false;
}
}
public BufferedWriter getFile(String path)
{
try
{
File file = new File(path);
if (!file.exists())
{
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
return new BufferedWriter(fw);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}
异常堆栈:{解析之前}
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.cnh.socket.client.ThreadListener.appendFile(ThreadListener.java:73)
at com.cnh.socket.client.ThreadListener.access$0(ThreadListener.java:65)
at com.cnh.socket.client.ThreadListener$ListenFor0X28.run(ThreadListener.java:48)
at java.lang.Thread.run(Unknown Source)
Data received in unknown format java.io.EOFException
答案 0 :(得分:2)
在客户端
if (!(in.read() == -1))
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
bw.write(canData.toString());
}
第一行从输入流中读取一个字节。这实际上是服务器写入的对象的第一个字节。因此,流不再正确对齐,因此以下readObject()
失败。
答案 1 :(得分:1)
您应该删除无意义和错误的read()
调用,这会使您的对象流不同步。
在您访问它时,您还可以删除对isConnected()
的所有冗余呼叫。他们什么都没做。你似乎有一种狂热来调用额外的方法,这些方法大多不做任何事情,或者试图预测未来。试着逐渐减少。
编辑根据要求,我不仅要批评您的客户,还要批评您的服务器代码。
服务器:
private void structureData(CANDataInfo canDataInfo)
{
try
{
if(server == null)
应该在构造函数中创建和配置ServerSocket
。
{
server = new ServerSocket(38301);
server.setSoTimeout(0);
零是默认值。不要断言默认值。删除。
}
client = server.accept();
Log.e("Server ", ""+client.isConnected());
记录isConnected()
是多余的。去掉。这将始终打印true
。套接字已连接。你刚刚接受了它。如果要记录有用的内容,请记录客户端套接字的远程地址。
Log.e("Data ", ""+canDataInfo.toString());
当你还没有读过任何数据时怎么样?如果这是不变的服务器端数据,为什么要在每次接受时都记录它?
if(!client.isConnected())
{
Log.e("Server ", "client.isConnected() "+client.isConnected());
server.close();
}
此测试永远无法通过,并且永远不会输入代码块,如果输入了一些奇迹,关闭服务器套接字是一个荒谬的回应。删除所有这些。
out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(canDataInfo);
out.close();
}
catch (Exception ex)
不要抓住Exception
。抓住IOException
。
{
Log.e(CANManagerSetUp.TAG, "" + ex);
您应该记录异常类,其消息和堆栈跟踪。 ""+ex
没有实现这一点。
}
}
客户端:
public class ThreadListener
{
Socket client = null;
ObjectInputStream in = null;
ListenFor0X28 runnableListenFor0X28 = null;
boolean continueMe;
public class ListenFor0X28 implements Runnable
{
JLabel jLab0x28;
public ListenFor0X28(){}
public ListenFor0X28(boolean stop, JLabel jLab0x28)
{
continueMe = stop;
this.jLab0x28 = jLab0x28;
}
public void run()
{
while(continueMe)
{
try
{
client = new Socket("localhost", 38301);
in = new ObjectInputStream(client.getInputStream());
if(client.isConnected())
客户端已连接。您构建Socket
时刚刚连接了它。如果通过一些奇迹它没有连接,调用getInputStream()
已经失败了SocketException
。删除此测试。一般来说,对代码中的错误或不可能错误的事情进行了太多测试。
{
jLab0x28.setText("Connected to Server");
appendFile(continueMe, jLab0x28, client);
}
else
{
System.out.println("Client is trying to connect");
jLab0x28.setText("Client is trying to connect");
}
}
else
块无法访问,日志消息'Client is trying to connect'
不正确。删除整个块和else
。
catch(Exception ex)
见上文。不要抓住Exception
。捕获编译器告诉您捕获的异常:在本例中为IOException
以及与DNS相关的异常。
{
ex.printStackTrace();
System.err.println("Before Append "+ex.toString());
请参阅上文有关如何记录异常的信息。
}
}
}
}
BufferedWriter file = getFile("C:\\ISSUE124_Resolved.txt");
private void appendFile(boolean continueMe, JLabel jLab0x28, Socket client)
{
try
{
if(!client.isClosed())
{
try
{
CANDataInfo canData = (CANDataInfo) in.readObject();
System.out.println(canData.toString());
file.write(canData.toString());
file.flush();
}
catch (EOFException exp)
{
continueMe = true;
System.out.println("A Stream has finished "+exp.toString()+"\n");
}
catch (ClassNotFoundException exp)
{
exp.printStackTrace();
System.err.println(exp.toString());
continueMe = false;
}
}
if(!continueMe)
{
file.close();
client.close();
in.close();
您无需关闭输入流和套接字。要么会这样做。通常的做法是关闭最外面的编写器/输出流(如果有),否则关闭输入流。
jLab0x28.setText("Socket is closed "+client.isClosed());
}
}
catch(IOException exp)
{
exp.printStackTrace();
System.err.println("Exception "+exp.toString());
jLab0x28.setText(exp.getMessage());
continueMe = false;
}
}
public BufferedWriter getFile(String path)
{
try
{
File file = new File(path);
if (!file.exists())
{
file.createNewFile();
}
您在这里(1)测试文件是否存在以及(2)创建新文件。
FileWriter fw = new FileWriter(file.getAbsoluteFile());
无论您在上面做了什么,操作系统都会创建一个新文件。因此exists()/createNewFile()
部分完全浪费时间:两个系统调用完全没有任何结果。删除它们。
return new BufferedWriter(fw);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
糟糕的做法。你应该让这个方法抛出IOException
而不是在内部捕获它,或者返回null
。目前,如果此方法失败,当您使用其返回值时,您将获得一个可引用的NullPointerException
。
}
}