【问题标题】:Java sending byte[] through sockets...wrong length readJava通过套接字发送字节[] ...读取的长度错误
【发布时间】:2012-02-14 04:49:24
【问题描述】:

对于我的家庭作业,我有一个节点网络,它们相互传递消息。每个节点都连接到一定数量的其他节点(我使用 4 个进行测试)。每个链接都有一个权重,所有节点都计算了它们希望如何发送消息的最短路径。发送的每个数据包都由消息协议(硬编码的 int)、一个整数(表示有多少消息通过发送节点)以及数据包的路由路径组成。

每个节点的每个链接都有一个线程。每个 Link 中都有一个活动的 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){

    }
}

【问题讨论】:

  • 如果 Thilo 的回答是正确的,您应该投票(点击投票计数器上方的向上箭头)然后“接受”它(点击复选标记),以表明它是正确的。跨度>
  • 我正在等待计时器完成...没有足够的代表来投票。
  • 啊,我明白了。如果您创建第二个帐户(例如在 superuser.com 上)并链接它们,您将获得 100 个代表。

标签: java sockets


【解决方案1】:
int a = in.read(b,0,len);
if(a!=len){

那是行不通的。 InputStream 可能不会读取您想要的所有字节,它可能只读取当前可用的内容,并在不阻塞的情况下返回那么多。

quote the Javadocs(强调我的):

从输入流中读取多达 len 个字节的数据到一个字节数组中。尝试读取多达 len 个字节,但可能会读取较小的数字,可能为零。实际读取的字节数以整数形式返回。

您需要继续循环读取,直到获得所需的所有数据(或流完成)。

或者,由于您使用的是 DataInputStream,您也可以使用

in.readFully(b, 0, len);

它总是准确读取len 字节(阻塞直到它们到达,当没有足够的数据时抛出异常)。

【讨论】:

  • 请原谅我的无知,但我怎样才能在跟踪阅读长度的同时做到这一点?谢谢
  • 由于某种原因,我没有在 API 中看到 readFully()。它就像一个魅力。谢谢!
  • 这个答案救了我的命;在我的最终网络项目到期之前,我有 20 分钟的时间,但我遇到了一个我无法弄清楚的错误。我绝望地用谷歌搜索“java套接字读取的字节数不正确”。这是出现的第一个答案,并且效果很好。谢谢!
猜你喜欢
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
相关资源
最近更新 更多