我有一些代碼從多播套接字讀取數據直到用戶定義的結束時間。如果線程通過調用Thread.interrupt
(或通過您可以提出的任何其他用戶啓動的操作)中斷,我還想停止讀取數據。當線程中斷時,我無法弄清楚如何獲得通知。現有的代碼如下:Java獲取MulticastSocket.receive來拋出ClosedByInterruptException
// These are the constants I am given
final int mcastPort = ...;
final InetAddress mcastIP = ...;
final InetAddress ifaceIP = ...; // Null indicates all interfaces should be used
final Instant endTime = ...; // Time at which to stop processing
// Initialize a datagram
final byte[] buffer = new byte[1000];
final DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// Process incoming datagram packets
try (final MulticastSocket socket = new MulticastSocket(port)) {
socket.joinGroup(mcastIP);
if (ifaceIP != null)
socket.setInterface(ifaceIP);
do {
final Duration soTimeout = Duration.between(Instant.now(), endTime);
socket.setSoTimeout(soTimeout);
socket.receive(packet);
// Process packet
...
} while (true);
} catch (final SocketTimeoutException e) {
// Normal condition... the recording time has ended
} catch (final ClosedByInterruptException e) {
// Uh-oh... this never happens
} ...
我看到,有一個DatagramSocket.getChannel
方法,它返回一個DatagramChannel
,所以自然假定類型被用來讀/寫與底層插座。該假設是錯誤的,這意味着MulticastSocket
未實現InterruptibleChannel
。因此,MulticastSocket.receive
永遠不會拋出ClosedByInterruptException
。
我在網上搜索了一些例子,但無法弄清楚如何修改上面的代碼來使用DatagramChannel
而不是MulticastSocket
。我需要幫助的問題是:
- 如何在DatagramChannel上設置SO_TIMEOUT參數?
- 如何將
InetAddress
轉換爲NetworkInterface
對象?
以下是關於如何從MulticastSocket
到DatagramChannel
我的實現將我最好的猜測,以滿足我的要求:
// Initialize a buffer
final ByteBuffer buffer = ByteBuffer.allocate(1000);
try (final DatagramChannel mcastChannel = DatagramChannel.open()) {
mcastChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
mcastChannel.connect(new InetSocketAddress(port));
mcastChannel.join(mcastIP);
if (ifaceIP != null)
// HELP: this option requires an InterfaceAddress object,
// but I only have access to an InetAddress object
mcastChannel.setOption(StandardSocketOptions.IP_MULTICAST_IF, ifaceIP);
do {
final Duration soTimeout = Duration.between(Instant.now(), endTime);
// HELP: SO_TIMEOUT is not a member of StandardSocketOptions
mcastChannel.setOption(SO_TIMEOUT, ???);
mcastChannel.receive(buffer);
// Process packet
...
} while (true);
} ...
將這種方法甚至工作? DatagramChannel.receive
沒有列出SocketTimeoutException
作爲它能夠拋出的例外之一。如果這能起作用,那麼請讓我知道我需要如何將第二個實現更改爲與第一個實現相同,但是當客戶端調用Thread.interrupt
時能夠拋出ClosedByInterruptException
。如果沒有,那麼是否有人有任何其他想法來滿足在預定義時間停止數據報接收的要求,同時還提供了一種通過用戶交互來停止執行的方法?
不要對沒有引用的文本使用引號格式。 – EJP