【问题标题】:Sending UDP from Java to Python not working将 UDP 从 Java 发送到 Python 不起作用
【发布时间】:2019-11-22 23:50:28
【问题描述】:

目标

我正在尝试通过 UDP 从 Java 服务器向同一台机器上的 Python 客户端发送数据。

环境

  • 设备/操作系统: Jetson nano 和 Ubuntu 18.04.3 LTS(仿生海狸)
  • JavaC 版本: javac 11.0.4
  • Java 版本:
    • openjdk 版本“11.0.4”2019-07-16
    • OpenJDK 运行时环境(内部版本 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
    • OpenJDK 64 位服务器 VM(内部版本 11.0.4+11-post-Ubuntu-1ubuntu218.04.3,混合模式)

问题

我可以将数据从 Python 测试服务器(参见下面的代码)发送到 Python 测试客户端就好了。但是,如果我尝试将数据从 Java 测试服务器发送到 Python 测试客户端,似乎什么都没有到达。 Java 服务器不会抛出异常。

用 Python 测试客户端(工作

import socket

UDP_IP = "localhost"
UDP_PORT = 9999

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))

print("listening...")

while True:
    data, addr = sock.recvfrom(1024)
    print("received message from: ", addr)
    print("payload: ", data)

Python 中的测试服务器(工作

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto("Hello World", ("localhost", 9999))

Java 中的测试服务器(不工作或无法访问 python 客户端

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

public class TestSender {
    public static void main(String[] args) {
        try {
            byte[]         data    = "Hello world".getBytes();
            int            port    = 9999;
            InetAddress    address = InetAddress.getLocalHost();
            DatagramPacket packet  = new DatagramPacket(data, data.length, address, port);
            DatagramSocket socket  = new DatagramSocket();

            socket.send(packet);
            System.out.println("Data sent");

            socket.close();

        } catch (Exception e) {
            System.out.println("Something went wrong");
        }
    }
}

【问题讨论】:

  • 您可以尝试将InetAddress.getLocalHost() 更改为InetAddress.getByName("localhost")。可能,getLocalHost 正在返回您的网络设备地址,而不是环回地址 (127.0.0.1)。
  • 以上,返回的地址可能取决于您的系统,您可以打印出来查看。有关更多信息,请参阅此:stackoverflow.com/questions/2381316/…
  • 不要绑定到本地主机。绑定到 0.0.0.0。

标签: java python sockets udp localhost


【解决方案1】:

问题

InetAddress address = InetAddress.getLocalHost();

返回机器接口之一的地址。

解决方案

正如@Gomiero 建议的那样,使用任一

InetAddress address = InetAddress.getByName("127.0.0.1");
// or
InetAddress address = InetAddress.getByName("localhost");

解决了这个问题,因为在这种情况下客户端绑定到127.0.0.1 并且不接受来自任何其他 IP 地址的数据包。

注意

正如@user207421 在大多数情况下建议的那样,问题的正确解决方案是将客户端绑定到0.0.0.0,如下所示:

UDP_IP = "0.0.0.0"
UDP_PORT = 9999
sock.bind((UDP_IP, UDP_PORT))

将客户端绑定到0.0.0.0 解决了在服务器端使用InetAddress.getLocalHost() 的问题,因为它使客户端接受到其任何IP 地址的数据。

但是,我最终决定将客户端绑定到 127.0.0.1,因为我只需要来自本地计算机的数据。

【讨论】:

  • 我没有建议任何这样的事情,如果你绑定到 0.0.0.0,这是没有必要的,这是我建议的,也是正常的做法。
  • @user207421 你是对的,对不起,这不是你的建议,我正在改变它。但是,address = InetAddress.getByName("0.0.0.0"); 似乎不起作用。结果为java.net.BindException: Cannot assign requested address: Datagram send failed
  • 我也没这么说。我说 bind 到 0.0.0.0 而不是 localhost。这里唯一绑定到 localhost 的是 Python 代码。所有这些其他 Java 东西都被误导了。如果您不通过绑定阻止它,您应该能够通过其任何可访问的 IP 地址向主机发送数据。
  • @user207421 谢谢,现在我明白了,我最初没有意识到我应该在客户端进行一些更改。这正是我正在寻找的答案,因为我真的很困惑 InetAddress.getLocalHost(); 的原始示例不起作用。但是,将客户端绑定到127.0.0.1 正是我需要的,因为在这种情况下我不希望来自网络中另一台机器的数据。我只是没有充分考虑确切的机制......
猜你喜欢
  • 2012-11-09
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多