在Java中接收UDP数据

3

我正在尝试使用Java接收由PlayCap广播到网络地址192.168.103.255端口3000的UDP数据,但我在设置方面遇到了麻烦。以下是我的代码:

DatagramSocket socket = new DatagramSocket();
InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000);
socket.bind(address);

我在绑定调用中得到了“java.net.SocketException: already bound”的错误信息。我对网络编程不太熟悉,所以可能做错了什么。感谢任何帮助。

这是堆栈跟踪:

java.net.SocketException: already bound
    at java.net.DatagramSocket.bind(Unknown Source)
    at runner.main(runner.java:16)

1
一个服务(可能是你程序的旧版本)已经在端口3000上监听。要么终止该进程,要么找一个新的端口。 - st0le
4个回答

30

我不想复活一个旧的线程,但我认为这个问题的答案是错误的。当我使用类似的代码创建DatagramSocket时,我遇到了同样的问题。

DatagramSocket socket = new DatagramSocket();
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), 5566));

这会导致一个SocketException异常

Exception in thread "main" java.net.SocketException: already bound
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at testapplication.TestApplication.main(TestApplication.java:25)

Java结果:1

并不是因为有另一个进程占用了相同的端口,而是我在使用默认构造函数时创建了一个已经绑定的数据报套接字。

new DatagramSocket()
根据 javadoc

DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口。

因此,异常的原因是您试图绑定一个已绑定的套接字。要使它工作,您需要使用以下构造函数创建未绑定的套接字。
DatagramSocket socket = new DatagramSocket(null);
InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000);
socket.bind(address);

希望这可以帮到你...


非常有用的代码:DatagramSocket socket = new DatagramSocket(null);,谢谢! - a.parfenov

1

执行
netstat -a -o -n
从中可以找到该端口是否已经被绑定(甚至可以获取所有已绑定的端口)。如果是,则尝试使用其他端口 :)


我运行了那个命令,但端口没有列出(无论是IP地址192.168.103.255还是端口3000都没有在任何地方列出)。此外,我不能使用另一个端口,因为我正在尝试从我的本地机器接收从PlayCap(http://www.signal11.us/oss/playcap/)广播的数据,而且似乎我无法指定要广播的端口。 - ajlitzau13
数据来自你本机吗?你尝试过使用 InetSocketAddress address = new InetSocketAddress("localhost", 3000); 或 InetSocketAddress address = new InetSocketAddress("127.0.0.1", 3000); 吗? - Freak
192.168.103.255 不是我的 IP 地址,这是数据的目标地址,根据 WireShark 的显示。我需要进行端口转发或禁用 Windows 防火墙吗?是的,我已尝试了您的建议并且得到相同的“already bound”错误提示。 - ajlitzau13
好的,那请检查您的防火墙设置。您使用的是哪个操作系统?有时候,关闭防火墙然后再检查一下。 - Freak
我正在使用Windows 7,并在Eclipse Juno中进行编程。我刚刚尝试关闭Windows防火墙,但没有帮助。 - ajlitzau13

1

很可能您的应用程序正在运行两次。或者您可能正在执行相同的代码两次。即使是相同的应用程序在绑定两次时也可能失败。

对于初学者来说,经常发生的情况是他们没有关闭之前的尝试(我也遇到过这种情况),然后他们的端口已经被占用了。请确保添加适当的异常处理,例如弹出消息“端口已被占用”。

请注意,对于监听,通常只会绑定一个端口,而不需要显式地址(您可能需要使用“0.0.0.0”)。然后您可以接收广播和单播。

我用于监听广播的代码非常简单:

DatagramSocket s = new DatagramSocket();
s.bind(new InetSocketAddress(port))

请注意,我并不绑定到特定的地址,而只是绑定到一个端口。

我刚尝试使用了 "0.0.0.0" 并重新启动了我的机器,两次都出现了“已经绑定”的错误。根据 WireShark 的显示,192.168.103.255 是数据的目标地址。提供给我数据的人表示,这个地址是数据广播的位置(而不是我的 IP 地址)。我接收这个数据的方式正确吗? - ajlitzau13
不需要重新启动。使用系统工具(例如netstat)查看哪个进程正在监听该端口。尝试使用不同的端口是否有效?如果所有端口都出现相同的错误,则可能是策略问题(如Windows防火墙等)。或者您的应用程序绑定了两次,第二次失败了。 - Has QUIT--Anony-Mousse
我运行了netstat,但是地址和端口没有在任何地方列出。我尝试了不同的端口,但似乎无法绑定任何端口。我尝试了每个地址/端口,都给我相同的“已绑定”错误。我尝试关闭Windows防火墙,但没有帮助。我不认为我会绑定两次,因为我的应用程序只是我在原始帖子中列出的代码(当然在try-catch块内)。我还插入了您在帖子中列出的代码,但仍然对我尝试的任何端口都显示“已绑定”!这太令人沮丧了! - ajlitzau13
你使用的Java版本是哪个?它是否被沙箱化或类似的处理?你能否在问题中更新完整的堆栈跟踪信息? - Has QUIT--Anony-Mousse
我的Java版本是“1.7.0_09-b05”。我怎么知道它是否被沙箱化了?我添加了堆栈跟踪,但不幸的是我认为它不会很有帮助。 - ajlitzau13
Java applets例如通常运行在沙盒中。网页上的Java小程序将不被允许监听您本地网络上的UDP广播,我猜 - 至少不应该被允许这样做。但是它也应该给出不同的异常。也许尝试一个最小的代码示例,完全可以放入您的问题中。并且确实尝试一种不同的编程语言。如果这是防火墙/系统策略问题,它应该影响其他语言。如果您在C中也无法绑定,那就不是Java的错。 - Has QUIT--Anony-Mousse

0

检查端口3000,可能已被其他应用程序使用。尝试使用不同的端口。


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