Java通过套接字发送byte [] ...错误的长度读取

时间:2012-02-14 04:49:24

标签: java sockets

对于我的家庭作业,我有一个节点网络,它们将消息传递给对方。每个节点都连接到一定数量的其他节点(我使用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){

    }
}

1 个答案:

答案 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个字节(阻塞直到那些已经到达,在没有足够的数据时抛出异常)。