Java中的多线程UDP套接字编程

3
我刚刚设计了一个Java应用程序,可以让多个客户端通过一个服务器进行聊天。我使用了UDP套接字和多线程。我有一些关于这方面的问题:
客户端代码:
 private void sendMessage(String s) throws Exception  
    {
        byte b[] = s.getBytes();
        InetAddress address = InetAddress.getLocalHost();
        DatagramPacket packet = new DatagramPacket(b, b.length, address, PORT);
        socket.send(packet);
    }

根据这里的回答(希望我没有误解),getLocalHost()方法应该返回本地回环地址。但是因为我连接到了一个网络,它却返回了192.xxx.xx.xx。我的理解正确吗?
我处理发送数据包的服务器端代码如下:
 byte[] b = new byte[1024];
    while (true) 
    {
        try 
        {
            Arrays.fill(b, (byte)0);
            DatagramPacket packet = new DatagramPacket(b, b.length);
            socket.receive(packet);

            String content = new String(b, 0 , b.length);

            InetAddress clientAddress = packet.getAddress();
            int clientPort = packet.getPort();
            String id = clientAddress.toString() + ":" + clientPort;

当我打印ID时,它会给我:/192.168.56.1:64372 : 问候。但端口应该是我从客户端发送数据包的那个端口,对吗?如果不是,我做错了什么?最后,在发送一些数据包后,我会得到一个异常:java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:1046。这是因为1024字节大小的字节数组吗?提前感谢:]

你期望的本地主机地址是什么?在家庭网络中,192.168...地址听起来很合理。你可以在控制台上ping本地主机以查看它解析为哪个地址。应该与getLocalHost()返回的地址相同。 - Fildor
我也期望得到192.xx,但是当我断开网络后仍然获得了192.xx地址时我感到困惑。后来使用ipconfig发现我的ipv4地址是相同的。所以我认为这清除了一些疑虑,但我仍然不知道人们如何获取/127.0.0.1。 - previouslyactualname
你能展示完整的堆栈跟踪吗?负载是什么?它确实大于1024字节吗?使用相同和/或不同长度的不同有效载荷是否会出现相同的错误? - Fildor
这正是问题所在,错误会突然出现。我现在无法发布堆栈跟踪,等有空了再发。有时候我发送一个数据包后就会出现,有时候则需要发送6或7个数据包才会出现。而且我只在s.length()小于10的情况下使用了s.getBytes()。 - previouslyactualname
我刚刚创建了一个简单的客户端/服务器UDP示例:http://stackoverflow.com/a/42450123/2619908 - nono
1个回答

0

好的,你遇到了以下问题: 1. 接收端口不同 2. 你遇到了数组越界异常

对于第一个问题,我猜测是Java或者你的操作系统重新分配了端口,但无论如何你都能正确接收到数据!

对于第二个问题,你并不知道DatagramSocket将数据存储在哪里! 它可能在数组的任何位置,因此数据包会保存数据的偏移量和长度:

DatagramPacket p;
p.getLength()
p.getOffset()
p.getData()

就这样做。

byte[] b = new byte[1024];
while (true) 
{
   try 
   {
      // This is not needed! Just check how much data you get
      // Arrays.fill(b, (byte)0);
      DatagramPacket packet = new DatagramPacket(b, b.length);
      socket.receive(packet);

      // This is the easiest
      String content = new String(packet.getData());

这还是有点奇怪,因为您已经将所有数据设置为0,并且您没有读取超过1024 = b.length字节的数据。但是为了数据完整性,请一定使用getData()!!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接