【问题标题】:Java UDP - Packet Send ProblemJava UDP - 数据包发送问题
【发布时间】:2011-03-20 17:07:17
【问题描述】:

每次我尝试向某个地址发送 UDP 数据包时,都会出现以下异常:

java.lang.ArrayIndexOutOfBoundsException
    at java.net.PlainDatagramSocketImpl.send(Native Method)
    at java.net.DatagramSocket.send(DatagramSocket.java:625)
    at services.servicetypes.network.host.Server_UDP_Thread_Monitor.send(Server_UDP_Thread_Monitor.java:84)

直接指向socket发送函数——this.socket.send(packet);

在我的数据报包上放置一个断点后,我得到以下信息:

packet  DatagramPacket  java.net.DatagramPacket@52c4c57 
byte[]  #1248(length=16)    
offset  int 0   
length  int 16  
bufLength   int 16  
address Inet4Address    /192.168.0.101  
Static          
Inherited   
port    int 3889

我不清楚为什么会发生这种情况,如果有人能对这个问题有所了解,那就太好了。我最初的想法可能是数据报包元素之一是空的。

(基本来源)

ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(byteOut);

// Game type
out.writeInt(1);

// Client
out.writeInt(gamerToSend.getClientID());

// Position
out.writeFloat(gamerToSend.getX());
out.writeFloat(gamerToSend.getY());


DatagramPacket packet = new DatagramPacket
(
  byteOut.toByteArray(),
  byteOut.size(),
  gamerToSend.getInetAddress(),
  3887
);

this.socket.send(packet);

byteOut.close();
out.close();

INetAddress 信息:(IP 正确显示目标机器)

address Inet4Address    /192.168.0.101  /192.168.0.101  
Static      
INADDRSZ    int 4   4   
serialVersionUID    long    3286316764910316507 3286316764910316507 
loopback    int 2130706433  2130706433  
IPv4    int 1   1   
IPv6    int 2   2   
preferIPv6Address   boolean false   false   
nameService InetAddress$1   java.net.InetAddress$1@5bf0cf51 java.net.InetAddress$1@5bf0cf51 
serialVersionUID    long    3286316764910316507 3286316764910316507 
addressCache    InetAddress$Cache   java.net.InetAddress$Cache@1ebafdff java.net.InetAddress$Cache@1ebafdff 
negativeCache   InetAddress$Cache   java.net.InetAddress$Cache@679801c  java.net.InetAddress$Cache@679801c  
addressCacheInit    boolean true    true    
unknown_array   InetAddress[]   #1266(length=1) #1266(length=1) 
impl    Inet6AddressImpl    java.net.Inet6AddressImpl@12c9b196  java.net.Inet6AddressImpl@12c9b196  
lookupTable HashMap "size = 0"  "size = 0"  
$assertionsDisabled boolean true    true    
Inherited               
hostName                
address int -1062731675 -1062731675 
family  int 2   2   
canonicalHostName               
caport  int 3889    3889    

服务器源 http://pastebin.com/JCdjhFQM

【问题讨论】:

  • 你需要发布你的代码,这样我们才能看到你在做什么。
  • 抱歉,忘记了,添加源代码。

标签: java network-programming


【解决方案1】:

我怀疑这与使用缓冲的DataOutputStream,然后传递底层byte[]有关。

在创建数据包之前尝试out.flush()

【讨论】:

  • 我试过了,但和以前一样的错误。 out.flush(); DatagramPacket 数据包 = 新的 DatagramPacket....
  • 问题是很明显,长度与你传入的字节[]不匹配。在你的数据包之前,做一个byte[] foo = byteOut.toByteArray();并将foo.length作为大小传入.或者只是将byteOut.size() 与该长度进行比较,看看是否有区别。
  • byte[] foo = byteOut.toByteArray(); System.out.println("1~" + byteOut.size()); System.out.println("2~" + foo.length); 1~16 2~16 没区别...
  • 你写了 16 个字节,但你的数据包只有 13 个字节(来自你发布的调试数据)。
  • 我的错,我错误地添加了一些额外的数据。现在两者都显示 16 个字节,但问题仍然存在。
【解决方案2】:

错误不在您发布的部分。我将您的源代码封装在一个示例程序中,它可以正常工作。

package de.fencing_game.paul.examples;

import java.io.*;
import java.net.*;

/**
 */
public class UDPTest {

    private static class Gamer {
        int clientID;
        float x;
        float y;
        InetAddress address;

        public int getClientID() { return clientID; }
        public float getX() { return x; }
        public float getY() { return y; }
        public InetAddress getInetAddress() { return address; }
    }


    private DatagramSocket socket;


    public UDPTest() throws IOException
    {
        this.socket = new DatagramSocket();
    }


    public void sendPackage(Gamer gamerToSend)
        throws IOException
    {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        DataOutputStream out = new DataOutputStream(byteOut);

        // Game type
        out.writeInt(1);

        // Client
        out.writeInt(gamerToSend.getClientID());

        // Position
        out.writeFloat(gamerToSend.getX());
        out.writeFloat(gamerToSend.getY());

        DatagramPacket packet = new DatagramPacket
            (
                byteOut.toByteArray(),
                byteOut.size(),
                gamerToSend.getInetAddress(),
                3887
            );

        this.socket.send(packet);

        byteOut.close();
        out.close();
    }


    public static void main(String[] ignored)
        throws IOException
    {
        Gamer g = new Gamer();
        g.address = InetAddress.getByName("localhost");

        UDPTest sender = new UDPTest();
        sender.sendPackage(g);
    }

}

你有什么不同?

【讨论】:

    【解决方案3】:

    感谢您的帮助。

    似乎 InetAddress 在某处损坏,因为手动将其设置到远程计算机,如下所示:

    InetAddress addr = InetAddress.getByName("192.168.0.101");
    

    工作得很好,所以我还有更多的调试要做,但这就是问题所在。

    再次感谢您的帮助!

    【讨论】:

    • 确保接受您自己的答案,以便问题结束。
    猜你喜欢
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多