对于我的家庭作业,我有一个节点网络,它们将消息传递给对方。每个节点都连接到一定数量的其他节点(我使用4进行测试)。每个链路都有一个权重,所有节点都计算了他们希望如何发送消息的最短路径。发送的每个数据包都由消息协议(一个硬编码的int)组成,这个整数表示已经通过发送节点传递了多少消息,以及数据包的路由路径。
每个节点的每个链接都有一个线程。每个链接都有一个活动的Socket。通过在消息的开头添加一个4字节的int来告知消息的长度来发送数据包。
在我强调网络之前,一切正常。对于我的测试,有10个节点,我得到其中5个在一个没有Thread.sleep()的简单while()循环中发送10000个数据包。毫无例外,在if(a!= len)语句执行期间的某个时刻总会出现错误。
如果我能澄清任何事情,请告诉我。提前致谢!这是代码(来自链接线程;从节点本身调用send()和forward()):
protected void listen(){
byte[] b;
int len;
try{
DataInputStream in = new DataInputStream(sock.getInputStream());
while(true){
len = in.readInt();
b = new byte[len];
int a = in.read(b,0,len);
if(a!=len){
System.out.println("ERROR: " + a + "!=" + len);
throw new SocketException(); //may have to fix...this will happen when message is corrupt/incomplete
}
Message m = new Message(b);
int p = m.getProtocol();
switch (p){
case CDNP.PACKET:
owner.incrementTracker();
System.out.print("\n# INCOMMING TRACKER: " + m.getTracker() + "\n>>> ");
owner.forward(m);
}
}
}catch (IOException e){
e.printStackTrace();
}
}
public void send(int tracker){
String[] message = { Conv.is(CDNP.PACKET), Conv.is(tracker), owner.getMST().toString() };
Message m = new Message(message);
forward(m);
}
public synchronized void forward(Message m){
try{
OutputStream out = sock.getOutputStream();
//convert length to byte array of length 4
ByteBuffer bb = ByteBuffer.allocate(4+m.getLength());
bb.putInt(m.getLength());
bb.put(m.getBytes());
out.write(bb.array());
out.flush();
}catch (UnknownHostException e){
System.out.println("ERROR: Could not send to Router at " + sock.getRemoteSocketAddress().toString());
return;
}catch (IOException e1){
}
}
答案 0 :(得分:3)
int a = in.read(b,0,len);
if(a!=len){
那不行。 InputStream可能无法读取您想要的所有字节,它可能只读取现在可用的字节,并且可以在不阻塞的情况下返回那么多。
致quote the Javadocs(强调我的):
从输入流中读取 len个字节的数据到一个字节数组中。尝试读取len个字节,但可以读取较小的数字,可能为零。实际读取的字节数以整数形式返回。
您需要继续读取循环,直到获得所需的所有数据(或流完成)。
或者,由于您使用的是DataInputStream,因此您也可以使用
in.readFully(b, 0, len);
总是精确地读取len
个字节(阻塞直到那些已经到达,在没有足够的数据时抛出异常)。