在侦听数据包时,在localhost上调用DatagramSocket.connect()是否应该停止?

时间:2015-07-18 00:52:32

标签: java udp datagram

在Java中,DatagramSocket.connect(InetSocketaddress addr)应该过滤除了来自该端口/地址的数据包之外的所有数据包,但是当我调用该方法时(在后台线程中侦听数据包时),它会停止。

DatagramSocket datagramSocket = new DatagramSocket(8000);
InetAddress localAddress = InetAddress.getByName("localhost");//localhost/127.0.0.1
int destinationPort = 7000;
datagramSocket.connect(localAddress, destinationPort); // This stall the program

在调用" DatagramSocket.connect"之前打印语句。在调用" DatagramSocket.connect"之后打印出来但打印语句。不要。

更新

调用DatagramSocket.disconnect()时,我也陷入停滞状态。使用DatagramSocket.connect,无论我将参数指定为InetAddress和端口,还是当我将其组合为InetSocketAddress时,都会发生停顿。另一个奇怪的是,如果我继承DatagramSocket并在子类中调用synchronized方法,则类似的停顿结果。唯一奇怪的是它在整个子类中没有其他同步方法。

关于我的Java版本(在Ubuntu上下载的Oracle Java 8)的注释:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

我的Java安装如下: http://tecadmin.net/install-oracle-java-8-jdk-8-ubuntu-via-ppa/

^这是Java中的一个错误还是应该在datagramSocket.connect上停止?谁能解释这种行为? ^

2 个答案:

答案 0 :(得分:0)

我有预感:

DatagramSocket.receive在DatagramSocket对象上保存同步锁。然后,当我调用DatagramSocket.connect或DatagramSocket.disconnect时,这些方法也被同步,因此阻塞了。你在后台线程上有一个接收操作,这可以解释为什么在你在DatagramSocket的子类中引入的另一个同步方法调用也会发生阻塞。这种解释可能不正确(取决于连接和断开方法是否在DatagramSocket对象上同步),但它是我迄今为止最合乎逻辑的方法。

答案 1 :(得分:0)

您的诊断/预感似乎是合理的(根据您的答案)。您应该能够通过附加调试器来确认它,以便在应用程序锁定时查看哪些线程持有什么锁。

但我认为它指出了使用数据报套接字的方式存在的实际问题。数据报套接字本质上是单线程对象。按设计。如果您尝试同时使用来自多个线程的套接字,则可能会锁定。

从表面上看,你所做的事似乎完全没必要。如果你有一个后台线程已经在接收,那你为什么需要连接呢?它已经连接好了!

我认为您正在尝试使用来自另一个线程的DatagramSocket.connect调用来对另一个线程DatagramSocket.receive的远程IP /端口进行实时更改。它不会起作用。在OS系统调用级别上是不可能的,因此也不是在Java中。您需要做的是以下之一:

  • 配置后台线程以使用通配符地址等侦听所有传入的数据报。然后根据您的期望处理,发送或丢弃。

  • 配置多个后台线程,每个后台线程都有自己的数据报套接字。 (或者一个线程和多个套接字,并使用非阻塞I / O和NIO选择器机制来复用...)

  • 了解如何在重新连接之前取消阻止receive。 (不确定如何做到这一点,但是向后台线程发送interrupt可能会有效。close也会解锁它,但这会破坏DatagramSocket对象。)