EOF异常读取UDP
EOFExcepton reading UDP
当 UDP 数据包的接收者试图读取它时,我收到了 EOFException。负责读取和解码 UDP 数据包的实例称为 Engager 对象。它们包含一个在 Engager 的构造函数中创建的套接字,一个名为 getEngagementPacketSize 的方法是接收和读取数据包的地方。两种方法在这里一起引用:
public Engager(){
MulticastSocket s=null;
try{
s=new MulticastSocket(6789);
s.joinGroup(InetAddress.getByName("224.0.0.1"));
}catch(IOException ex){
ex.printStackTrace(System.out);
}
this.socket=s;
}
private int getEngagementPacketSize()throws Exception{
byte[]bytes=new byte[Integer.BYTES];
DatagramPacket dp=new DatagramPacket(bytes,Integer.BYTES);
this.socket.receive(dp);
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
ObjectInputStream ois=new ObjectInputStream(bais);
int eps=ois.readInt();
ois.close();
return eps;
}
调用ois.readInt()时出现异常。
在发送方,数据包是这样创建和发送的:
InetAddress ia=null;
try{
ia=InetAddress.getByName("224.0.0.1");
}catch(UnknownHostException ex){
NewInstance_CannotConstructMulticastDestination x=new NewInstance_CannotConstructMulticastDestination(ac);
x.initCause(ex);
throw x;
}
MulticastSocket ms=null;
try{
ms=new MulticastSocket(6789);
ms.joinGroup(ia);
}catch(IOException ex){
NewInstance_CannotConstructMulticastSocket x=new NewInstance_CannotConstructMulticastSocket(ac);
x.initCause(ex);
throw x;
}
NamedSovereignAlias nsa=new NamedSovereignAlias("Self");
Engagement engagement=new Engagement(nsa,nsa,ac.getName(),ac.getPresynapticDelegate());
byte[]engagementBytes=null;
ByteArrayOutputStream baosEngagement=new ByteArrayOutputStream();
try(ObjectOutputStream oos=new ObjectOutputStream(baosEngagement)){
oos.writeObject(engagement);
oos.close();
}catch(Exception ex){
NewInstance_CannotCreateBodyContent x=new NewInstance_CannotCreateBodyContent(ac);
x.initCause(ex);
throw x;
}
engagementBytes=baosEngagement.toByteArray();
byte[]epsBytes=null;
ByteArrayOutputStream baosEps=new ByteArrayOutputStream();
try(ObjectOutputStream oos=new ObjectOutputStream(baosEps)){
oos.writeInt(engagementBytes.length);
oos.close();
}catch(Exception ex){
NewInstance_CannotCreateHeadContent x=new NewInstance_CannotCreateHeadContent(ac);
x.initCause(ex);
throw x;
}
epsBytes=baosEps.toByteArray();
System.out.println("Length of header ["+epsBytes.length+"].");
try{
DatagramPacket dp=new DatagramPacket(epsBytes,epsBytes.length,ia,6789);
ms.send(dp);
}catch(Exception ex){
NewInstance_CannotSendHeadPacket x=new NewInstance_CannotSendHeadPacket(ac);
x.initCause(ex);
throw x;
}
我问这个问题是因为当我尝试读取两个 UDP 数据包中的第一个时,接收方收到 EOFException。因此,我的显示第二个数据包如何打包和发送的代码没有公开(它实际上被注释掉了,因此没有理由怀疑第二个数据包首先被接收)。第一个数据包仅包含一个整数,表示第二个数据包中的字节数。第二个数据包(如果已发送)包含一个 Engagement 实例。我没有在这里引用 Engagement class 因为它的长度(而不是它的形式)很重要。发件人告诉我第一个数据包的长度应该是 10 个字节;这就是在发送数据包之前在上面的列表中执行 System.println 语句时在系统输出 window 中观察到的结果。
为什么接收方无法从数据包中读取整数?问题出在发送方还是接收方?可以两者兼而有之吗?
大受帮助。谢谢,
欧文.
Is the problem in the sender or the receiver? Could it be both?
问题出在接收端。您正在这样分配数据包缓冲区:
byte[] bytes = new byte[Integer.BYTES];
太小了。如果您查看 Object Serialization Specification,您会看到序列化流以 2 字节 "magic number" 和 2 字节协议版本号开头。所以根据我的计算,缓冲区需要至少 8 个字节......可能更多。
当 UDP 数据包的接收者试图读取它时,我收到了 EOFException。负责读取和解码 UDP 数据包的实例称为 Engager 对象。它们包含一个在 Engager 的构造函数中创建的套接字,一个名为 getEngagementPacketSize 的方法是接收和读取数据包的地方。两种方法在这里一起引用:
public Engager(){
MulticastSocket s=null;
try{
s=new MulticastSocket(6789);
s.joinGroup(InetAddress.getByName("224.0.0.1"));
}catch(IOException ex){
ex.printStackTrace(System.out);
}
this.socket=s;
}
private int getEngagementPacketSize()throws Exception{
byte[]bytes=new byte[Integer.BYTES];
DatagramPacket dp=new DatagramPacket(bytes,Integer.BYTES);
this.socket.receive(dp);
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
ObjectInputStream ois=new ObjectInputStream(bais);
int eps=ois.readInt();
ois.close();
return eps;
}
调用ois.readInt()时出现异常。
在发送方,数据包是这样创建和发送的:
InetAddress ia=null;
try{
ia=InetAddress.getByName("224.0.0.1");
}catch(UnknownHostException ex){
NewInstance_CannotConstructMulticastDestination x=new NewInstance_CannotConstructMulticastDestination(ac);
x.initCause(ex);
throw x;
}
MulticastSocket ms=null;
try{
ms=new MulticastSocket(6789);
ms.joinGroup(ia);
}catch(IOException ex){
NewInstance_CannotConstructMulticastSocket x=new NewInstance_CannotConstructMulticastSocket(ac);
x.initCause(ex);
throw x;
}
NamedSovereignAlias nsa=new NamedSovereignAlias("Self");
Engagement engagement=new Engagement(nsa,nsa,ac.getName(),ac.getPresynapticDelegate());
byte[]engagementBytes=null;
ByteArrayOutputStream baosEngagement=new ByteArrayOutputStream();
try(ObjectOutputStream oos=new ObjectOutputStream(baosEngagement)){
oos.writeObject(engagement);
oos.close();
}catch(Exception ex){
NewInstance_CannotCreateBodyContent x=new NewInstance_CannotCreateBodyContent(ac);
x.initCause(ex);
throw x;
}
engagementBytes=baosEngagement.toByteArray();
byte[]epsBytes=null;
ByteArrayOutputStream baosEps=new ByteArrayOutputStream();
try(ObjectOutputStream oos=new ObjectOutputStream(baosEps)){
oos.writeInt(engagementBytes.length);
oos.close();
}catch(Exception ex){
NewInstance_CannotCreateHeadContent x=new NewInstance_CannotCreateHeadContent(ac);
x.initCause(ex);
throw x;
}
epsBytes=baosEps.toByteArray();
System.out.println("Length of header ["+epsBytes.length+"].");
try{
DatagramPacket dp=new DatagramPacket(epsBytes,epsBytes.length,ia,6789);
ms.send(dp);
}catch(Exception ex){
NewInstance_CannotSendHeadPacket x=new NewInstance_CannotSendHeadPacket(ac);
x.initCause(ex);
throw x;
}
我问这个问题是因为当我尝试读取两个 UDP 数据包中的第一个时,接收方收到 EOFException。因此,我的显示第二个数据包如何打包和发送的代码没有公开(它实际上被注释掉了,因此没有理由怀疑第二个数据包首先被接收)。第一个数据包仅包含一个整数,表示第二个数据包中的字节数。第二个数据包(如果已发送)包含一个 Engagement 实例。我没有在这里引用 Engagement class 因为它的长度(而不是它的形式)很重要。发件人告诉我第一个数据包的长度应该是 10 个字节;这就是在发送数据包之前在上面的列表中执行 System.println 语句时在系统输出 window 中观察到的结果。
为什么接收方无法从数据包中读取整数?问题出在发送方还是接收方?可以两者兼而有之吗?
大受帮助。谢谢,
欧文.
Is the problem in the sender or the receiver? Could it be both?
问题出在接收端。您正在这样分配数据包缓冲区:
byte[] bytes = new byte[Integer.BYTES];
太小了。如果您查看 Object Serialization Specification,您会看到序列化流以 2 字节 "magic number" 和 2 字节协议版本号开头。所以根据我的计算,缓冲区需要至少 8 个字节......可能更多。