8335771: Improve stability of java/nio/channels/DatagramChannel tests
Reviewed-by: alanb
This commit is contained in:
parent
2766b09e29
commit
3ca359ad22
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,6 +48,7 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import static java.net.StandardSocketOptions.*;
|
||||
import static java.net.StandardProtocolFamily.*;
|
||||
import static jdk.test.lib.NetworkConfiguration.isSameInterface;
|
||||
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
@ -295,8 +296,8 @@ public class AdaptorMulticasting {
|
||||
|
||||
// setNetworkInterface
|
||||
s.setNetworkInterface(ni);
|
||||
assertTrue(s.getNetworkInterface().equals(ni));
|
||||
assertTrue(s.getOption(IP_MULTICAST_IF).equals(ni));
|
||||
assertTrue(isSameInterface(s.getNetworkInterface(), ni));
|
||||
assertTrue(isSameInterface(s.getOption(IP_MULTICAST_IF), ni));
|
||||
InetAddress address = s.getInterface();
|
||||
assertTrue(ni.inetAddresses().filter(address::equals).findAny().isPresent());
|
||||
|
||||
@ -315,8 +316,8 @@ public class AdaptorMulticasting {
|
||||
|
||||
// setOption(IP_MULTICAST_IF)
|
||||
s.setOption(IP_MULTICAST_IF, ni);
|
||||
assertTrue(s.getOption(IP_MULTICAST_IF).equals(ni));
|
||||
assertTrue(s.getNetworkInterface().equals(ni));
|
||||
assertTrue(isSameInterface(s.getOption(IP_MULTICAST_IF), ni));
|
||||
assertTrue(isSameInterface(s.getNetworkInterface(), ni));
|
||||
|
||||
// bad values for IP_MULTICAST_IF
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
@ -412,7 +413,8 @@ public class AdaptorMulticasting {
|
||||
assertTrue(s.getOption(IP_MULTICAST_IF) != null);
|
||||
|
||||
SocketAddress target = new InetSocketAddress(group, s.getLocalPort());
|
||||
byte[] message = "hello".getBytes("UTF-8");
|
||||
String msg = "AdaptorMulticasting: " + System.nanoTime();
|
||||
byte[] message = msg.getBytes("UTF-8");
|
||||
|
||||
// send message to multicast group
|
||||
DatagramPacket p = new DatagramPacket(message, message.length);
|
||||
@ -421,8 +423,22 @@ public class AdaptorMulticasting {
|
||||
|
||||
// receive message
|
||||
s.setSoTimeout(0);
|
||||
p = new DatagramPacket(new byte[1024], 100);
|
||||
s.receive(p);
|
||||
while (true) {
|
||||
p = new DatagramPacket(new byte[1024], 100);
|
||||
s.receive(p);
|
||||
if (p.getPort() == s.getLocalPort()) {
|
||||
String str = new String(p.getData(), p.getOffset(), p.getLength(), "UTF-8");
|
||||
if (Arrays.equals(p.getData(), p.getOffset(), p.getLength(), message, 0, message.length)) {
|
||||
System.out.format("Got expected message \"%s\" from %s%n", str, p.getSocketAddress());
|
||||
break;
|
||||
}
|
||||
System.out.println("Unexpected message received. Expected: " + msg);
|
||||
System.out.println("Received message doesn't match - skipping: " + str);
|
||||
} else {
|
||||
System.out.println("Unexpected message received. Expected message from: " + s.getLocalAddress());
|
||||
System.out.println("Received message sender doesn't match - skipping: " + p.getSocketAddress());
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(p.getLength() == message.length);
|
||||
assertTrue(p.getPort() == s.getLocalPort());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.BindException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetSocketAddress;
|
||||
@ -46,6 +47,7 @@ import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
@ -54,6 +56,38 @@ import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class AfterDisconnect {
|
||||
|
||||
interface RetryableTest<T extends Exception> {
|
||||
public void runTest() throws T;
|
||||
}
|
||||
|
||||
// retry the given lambda (RetryableTest) if an exception
|
||||
// that satisfies the predicate (retryOn) is caught.
|
||||
<T extends Exception> void testWithRetry(RetryableTest<T> test,
|
||||
Predicate<Throwable> retryOn,
|
||||
int max) throws T {
|
||||
for (int i=0; i < max; i++) {
|
||||
try {
|
||||
test.runTest();
|
||||
break;
|
||||
} catch (Throwable t) {
|
||||
if (i < max -1 && retryOn.test(t)) {
|
||||
System.out.println("Got " + t + "; will retry");
|
||||
} else throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When calling {@link DatagramChannel#disconnect()} a {@link BindException}
|
||||
* may occur. In which case we want to retry the test.
|
||||
*/
|
||||
class BindExceptionOnDisconnect extends BindException {
|
||||
BindExceptionOnDisconnect(BindException x) {
|
||||
super(x.getMessage());
|
||||
initCause(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void execute() throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
@ -61,34 +95,41 @@ public class AfterDisconnect {
|
||||
InetAddress lb = InetAddress.getLoopbackAddress();
|
||||
|
||||
// test with default protocol family
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
System.out.println("Test with default");
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
|
||||
// test with IPv6 socket
|
||||
if (IPSupport.hasIPv6()) {
|
||||
System.out.println("Test with IPv6 socket");
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) {
|
||||
System.out.println("Test with default");
|
||||
testWithRetry(() -> {
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
}, BindExceptionOnDisconnect.class::isInstance, 5);
|
||||
|
||||
// test with IPv6 socket
|
||||
if (IPSupport.hasIPv6()) {
|
||||
System.out.println("Test with IPv6 socket");
|
||||
testWithRetry(() -> {
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) {
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
}, BindExceptionOnDisconnect.class::isInstance, 5);
|
||||
}
|
||||
|
||||
// test with IPv4 socket
|
||||
if (IPSupport.hasIPv4() && !preferIPv6) {
|
||||
System.out.println("Test with IPv4 socket");
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) {
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
testWithRetry(() -> {
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) {
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
}, BindExceptionOnDisconnect.class::isInstance, 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test(DatagramChannel dc) throws IOException {
|
||||
testLocalAddress(dc);
|
||||
testSocketOptions(dc);
|
||||
@ -111,7 +152,11 @@ public class AfterDisconnect {
|
||||
assertEquals(dc.getLocalAddress(), local);
|
||||
assertEquals(dc.getRemoteAddress(), remote);
|
||||
|
||||
dc.disconnect();
|
||||
try {
|
||||
dc.disconnect();
|
||||
} catch (BindException x) {
|
||||
throw new BindExceptionOnDisconnect(x);
|
||||
}
|
||||
assertFalse(dc.isConnected());
|
||||
assertEquals(dc.getLocalAddress(), local);
|
||||
assertTrue(dc.getRemoteAddress() == null);
|
||||
@ -134,7 +179,11 @@ public class AfterDisconnect {
|
||||
Map<SocketOption<?>, Object> map = options(dc);
|
||||
|
||||
dc.connect(dc.getLocalAddress());
|
||||
dc.disconnect();
|
||||
try {
|
||||
dc.disconnect();
|
||||
} catch (BindException x) {
|
||||
throw new BindExceptionOnDisconnect(x);
|
||||
}
|
||||
|
||||
// check socket options have not changed
|
||||
assertEquals(map, options(dc));
|
||||
@ -168,7 +217,11 @@ public class AfterDisconnect {
|
||||
sel.selectNow();
|
||||
|
||||
dc.connect(dc.getLocalAddress());
|
||||
dc.disconnect();
|
||||
try {
|
||||
dc.disconnect();
|
||||
} catch (BindException x) {
|
||||
throw new BindExceptionOnDisconnect(x);
|
||||
}
|
||||
|
||||
// selection key should still be valid
|
||||
assertTrue(key.isValid());
|
||||
@ -210,7 +263,11 @@ public class AfterDisconnect {
|
||||
MembershipKey key = dc.join(group, ni);
|
||||
|
||||
dc.connect(dc.getLocalAddress());
|
||||
dc.disconnect();
|
||||
try {
|
||||
dc.disconnect();
|
||||
} catch (BindException x) {
|
||||
throw new BindExceptionOnDisconnect(x);
|
||||
}
|
||||
|
||||
// membership key should still be valid
|
||||
assertTrue(key.isValid());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,6 +23,8 @@
|
||||
|
||||
/* @test
|
||||
* @bug 4313882 7183800
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Platform Connect
|
||||
* @run main/othervm Connect
|
||||
* @summary Test DatagramChannel's send and receive methods
|
||||
*/
|
||||
@ -38,6 +40,8 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
public class Connect {
|
||||
@ -114,9 +118,21 @@ public class Connect {
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(MAX);
|
||||
bb.put(bytes);
|
||||
bb.flip();
|
||||
// When connecting an unbound datagram channel, the underlying
|
||||
// socket will first be bound to the wildcard address. On macOS,
|
||||
// the system may allocate the same port on which another socket
|
||||
// is already bound with a more specific address. This may prevent
|
||||
// datagrams directed at the connected socket to reach it.
|
||||
// To avoid this, when on macOS, we preemptively bind `dc` to the
|
||||
// specific address instead of letting it bind to the wildcard.
|
||||
if (Platform.isOSX()) {
|
||||
dc.bind(new InetSocketAddress(((InetSocketAddress)connectSocketAddress).getAddress(), 0));
|
||||
err.println("Initiator bound to: " + connectSocketAddress);
|
||||
}
|
||||
err.println("Initiator connecting to: " + connectSocketAddress);
|
||||
dc.connect(connectSocketAddress);
|
||||
err.println("Initiator bound to: " + dc.getLocalAddress());
|
||||
assert !connectSocketAddress.equals(dc.getLocalAddress());
|
||||
|
||||
// Send a message
|
||||
err.println("Initiator attempting to write to Responder at " + connectSocketAddress);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,7 @@
|
||||
/* @test
|
||||
* @bug 8234805 8235193
|
||||
* @summary Test DatagramChannel send/receive and that receive returns the expected
|
||||
* sender address
|
||||
* sender address.
|
||||
* @run main/othervm ManySourcesAndTargets
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true ManySourcesAndTargets
|
||||
*/
|
||||
@ -63,6 +63,7 @@ public class ManySourcesAndTargets {
|
||||
try (DatagramChannel reader = DatagramChannel.open()) {
|
||||
// bind reader to wildcard address so it can receive from any address
|
||||
reader.bind(new InetSocketAddress(0));
|
||||
System.out.println("\nReader bound to: " + reader.getLocalAddress());
|
||||
for (InetAddress address : addresses) {
|
||||
System.out.format("%n-- %s --%n", address.getHostAddress());
|
||||
|
||||
@ -75,6 +76,7 @@ public class ManySourcesAndTargets {
|
||||
try (DatagramChannel sender = DatagramChannel.open()) {
|
||||
// bind sender to wildcard address so it can send to any address
|
||||
sender.bind(new InetSocketAddress(0));
|
||||
System.out.println("\nSender bound to: " + sender.getLocalAddress());
|
||||
for (InetAddress address : addresses) {
|
||||
System.out.format("%n-- %s --%n", address.getHostAddress());
|
||||
|
||||
@ -97,6 +99,11 @@ public class ManySourcesAndTargets {
|
||||
sender.bind(new InetSocketAddress(address, 0));
|
||||
|
||||
SocketAddress local = sender.getLocalAddress();
|
||||
System.out.println("Sender bound to: " + local);
|
||||
if (((InetSocketAddress)local).getPort() == remotePort) {
|
||||
System.out.println("testSend: Sender and reader have same port: skipping");
|
||||
return;
|
||||
}
|
||||
byte[] bytes = serialize(local);
|
||||
|
||||
SocketAddress previousSource = null;
|
||||
@ -105,6 +112,8 @@ public class ManySourcesAndTargets {
|
||||
sender.send(ByteBuffer.wrap(bytes), remote);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(1000);
|
||||
System.out.format("testSend: reader waiting to receive at: %s%n",
|
||||
reader.getLocalAddress());
|
||||
SocketAddress source = reader.receive(bb);
|
||||
System.out.format("received datagram from %s%n", source);
|
||||
|
||||
@ -138,11 +147,18 @@ public class ManySourcesAndTargets {
|
||||
|
||||
SocketAddress remote = reader.getLocalAddress();
|
||||
|
||||
System.out.println("Reader bound to: " + remote);
|
||||
if (((InetSocketAddress)local).getPort() == ((InetSocketAddress)remote).getPort()) {
|
||||
System.out.println("testReceive: Sender and reader have same port: skipping");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
System.out.format("send %s -> %s%n", local, remote);
|
||||
sender.send(ByteBuffer.allocate(32), remote);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(1000);
|
||||
System.out.format("testReceive: reader waiting to receive at: %s%n",
|
||||
reader.getLocalAddress());
|
||||
SocketAddress source = reader.receive(bb);
|
||||
System.out.format("received datagram from %s%n", source);
|
||||
}
|
||||
@ -165,7 +181,12 @@ public class ManySourcesAndTargets {
|
||||
|
||||
private static Optional<NetworkInterface> networkInterface(InetAddress ia) {
|
||||
try {
|
||||
return Optional.ofNullable(NetworkInterface.getByInetAddress(ia));
|
||||
NetworkInterface nif = NetworkInterface.getByInetAddress(ia);
|
||||
if (nif != null) {
|
||||
System.out.format("Selecting interface %s[%d]%n\twith addresses:%n\t%s%n",
|
||||
nif.getDisplayName(), nif.getIndex(), nif.inetAddresses().toList());
|
||||
}
|
||||
return Optional.ofNullable(nif);
|
||||
} catch (SocketException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -99,15 +99,25 @@ public class MulticastSendReceiveTests {
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(100);
|
||||
|
||||
try {
|
||||
long elapsed = 0;
|
||||
for (;;) {
|
||||
System.out.println("Waiting to receive message");
|
||||
long start = System.nanoTime();
|
||||
sel.select(5*1000);
|
||||
long waited = (System.nanoTime() - start) / 1000_000;
|
||||
elapsed += waited;
|
||||
buf.clear();
|
||||
SocketAddress sa = dc.receive(buf);
|
||||
|
||||
// no datagram received
|
||||
if (sa == null) {
|
||||
if (expectedSender != null) {
|
||||
throw new RuntimeException("Expected message not received");
|
||||
if (elapsed > 4800) {
|
||||
throw new RuntimeException("Expected message not received");
|
||||
} else {
|
||||
sel.selectedKeys().clear();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
System.out.println("No message received (correct)");
|
||||
return;
|
||||
@ -123,8 +133,8 @@ public class MulticastSendReceiveTests {
|
||||
int receivedId = -1;
|
||||
try {
|
||||
receivedId = Integer.parseInt(s);
|
||||
System.out.format("Received message from %s (id=0x%x)\n",
|
||||
sender, receivedId);
|
||||
System.out.format("Received message from %s (id=0x%x, length=%s)\n",
|
||||
sender, receivedId, bytes.length);
|
||||
} catch (NumberFormatException x) {
|
||||
System.out.format("Received message from %s (msg=%s)\n", sender, s);
|
||||
}
|
||||
@ -142,7 +152,6 @@ public class MulticastSendReceiveTests {
|
||||
}
|
||||
|
||||
sel.selectedKeys().clear();
|
||||
buf.rewind();
|
||||
}
|
||||
} finally {
|
||||
sel.close();
|
||||
@ -160,6 +169,8 @@ public class MulticastSendReceiveTests {
|
||||
throws IOException
|
||||
{
|
||||
System.out.format("\nTest DatagramChannel to %s socket\n", family.name());
|
||||
System.out.format("With interface=%s[%s]%n\twith bound addresses:%n\t%s%n",
|
||||
nif.getDisplayName(), nif.getIndex(), nif.inetAddresses().toList());
|
||||
try (DatagramChannel dc = (family == UNSPEC) ?
|
||||
DatagramChannel.open() : DatagramChannel.open(family)) {
|
||||
dc.setOption(StandardSocketOptions.SO_REUSEADDR, true)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,19 +24,26 @@
|
||||
/* @test
|
||||
* @bug 4512723 6621689
|
||||
* @summary Test that connect/send/receive with unbound DatagramChannel causes
|
||||
* the channel's socket to be bound to a local address
|
||||
* the channel's socket to be bound to a local address.
|
||||
* @run main/othervm NotBound
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class NotBound {
|
||||
|
||||
static final CountDownLatch received = new CountDownLatch(1);
|
||||
|
||||
static void checkBound(DatagramChannel dc) throws IOException {
|
||||
if (dc.getLocalAddress() == null)
|
||||
throw new RuntimeException("Not bound??");
|
||||
System.out.println("Bound to: " + dc.getLocalAddress());
|
||||
}
|
||||
|
||||
// starts a thread to send a datagram to the given channel once the channel
|
||||
@ -51,19 +58,44 @@ public class NotBound {
|
||||
Thread.sleep(50);
|
||||
local = (InetSocketAddress)dc.getLocalAddress();
|
||||
} while (local == null);
|
||||
System.out.format("receiver bound to: %s%n", local);
|
||||
|
||||
// send message to channel to wakeup receiver
|
||||
DatagramChannel sender = DatagramChannel.open();
|
||||
try {
|
||||
ByteBuffer bb = ByteBuffer.wrap("hello".getBytes());
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
SocketAddress target =
|
||||
new InetSocketAddress(lh, local.getPort());
|
||||
sender.send(bb, target);
|
||||
} finally {
|
||||
sender.close();
|
||||
boolean isAnyLocal = local.getAddress().isAnyLocalAddress();
|
||||
int maxAttempts = 5;
|
||||
int localPort = 0;
|
||||
List<InetAddress> llh = isAnyLocal
|
||||
? List.of(InetAddress.getLocalHost(), InetAddress.getLoopbackAddress())
|
||||
: List.of(local.getAddress());
|
||||
SocketAddress target = null;
|
||||
for (int i = 0 ; i < maxAttempts ; i++) {
|
||||
InetAddress lh = llh.get(i % llh.size());
|
||||
target = new InetSocketAddress(lh, local.getPort());
|
||||
// send message to channel to wakeup receiver
|
||||
try (DatagramChannel sender = DatagramChannel.open()) {
|
||||
ByteBuffer bb = ByteBuffer.wrap("NotBound: hello".getBytes());
|
||||
sender.send(bb, target);
|
||||
System.out.format("Woke up receiver: sent datagram to %s from %s%n",
|
||||
target, sender.getLocalAddress());
|
||||
localPort = ((InetSocketAddress)sender.getLocalAddress()).getPort();
|
||||
}
|
||||
if (received.await(250, TimeUnit.MILLISECONDS)) {
|
||||
// The datagram has been received: no need to continue
|
||||
// sending
|
||||
break;
|
||||
}
|
||||
// if sender port and destination port were identical, which
|
||||
// could happen on some systems, the receiver might not receive
|
||||
// the datagram. So in that case we try again, bailing out if
|
||||
// we had to retry too many times
|
||||
if (localPort == local.getPort()) {
|
||||
System.out.println("Local port and peer port are identical. Retrying...");
|
||||
} else {
|
||||
System.out.println("Datagram not received after 250ms. Retrying...");
|
||||
}
|
||||
}
|
||||
if (localPort == local.getPort()) {
|
||||
System.out.println("Couldn't find a port to send to " + target);
|
||||
}
|
||||
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
@ -77,14 +109,12 @@ public class NotBound {
|
||||
// connect
|
||||
dc = DatagramChannel.open();
|
||||
try {
|
||||
DatagramChannel peer = DatagramChannel.open()
|
||||
.bind(new InetSocketAddress(0));
|
||||
int peerPort = ((InetSocketAddress)(peer.getLocalAddress())).getPort();
|
||||
try {
|
||||
System.out.println("Check that connect() binds the socket");
|
||||
try (DatagramChannel peer = DatagramChannel.open()) {
|
||||
peer.bind(new InetSocketAddress(0));
|
||||
int peerPort = ((InetSocketAddress)(peer.getLocalAddress())).getPort();
|
||||
dc.connect(new InetSocketAddress(InetAddress.getLocalHost(), peerPort));
|
||||
checkBound(dc);
|
||||
} finally {
|
||||
peer.close();
|
||||
}
|
||||
} finally {
|
||||
dc.close();
|
||||
@ -93,7 +123,8 @@ public class NotBound {
|
||||
// send
|
||||
dc = DatagramChannel.open();
|
||||
try {
|
||||
ByteBuffer bb = ByteBuffer.wrap("ignore this".getBytes());
|
||||
System.out.println("Check that send() binds the socket");
|
||||
ByteBuffer bb = ByteBuffer.wrap("NotBound: ignore this".getBytes());
|
||||
SocketAddress target =
|
||||
new InetSocketAddress(InetAddress.getLocalHost(), 5000);
|
||||
dc.send(bb, target);
|
||||
@ -105,9 +136,11 @@ public class NotBound {
|
||||
// receive (blocking)
|
||||
dc = DatagramChannel.open();
|
||||
try {
|
||||
System.out.println("Check that blocking receive() binds the socket");
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(128);
|
||||
wakeupWhenBound(dc);
|
||||
SocketAddress sender = dc.receive(bb);
|
||||
received.countDown();
|
||||
if (sender == null)
|
||||
throw new RuntimeException("Sender should not be null");
|
||||
checkBound(dc);
|
||||
@ -118,6 +151,7 @@ public class NotBound {
|
||||
// receive (non-blocking)
|
||||
dc = DatagramChannel.open();
|
||||
try {
|
||||
System.out.println("Check that non-blocking receive() binds the socket");
|
||||
dc.configureBlocking(false);
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(128);
|
||||
SocketAddress sender = dc.receive(bb);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -71,9 +71,11 @@ public class Promiscuous {
|
||||
dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, nif);
|
||||
byte[] msg = Integer.toString(id).getBytes("UTF-8");
|
||||
ByteBuffer buf = ByteBuffer.wrap(msg);
|
||||
System.out.format("Send message -> group %s (id=0x%x)\n",
|
||||
group.getHostAddress(), id);
|
||||
System.out.format("Send message -> group [%s]:%d (id=0x%x) nif:%s[%s]%n",
|
||||
group.getHostAddress(), port, id, nif.getDisplayName(), nif.getIndex());
|
||||
System.out.format("bound address before send: %s%n", dc.getLocalAddress());
|
||||
dc.send(buf, new InetSocketAddress(group, port));
|
||||
System.out.format("bound address after send: %s%n", dc.getLocalAddress());
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@ -97,15 +99,26 @@ public class Promiscuous {
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(100);
|
||||
|
||||
try {
|
||||
long elapsed = 0;
|
||||
for (;;) {
|
||||
System.out.println("Waiting to receive message");
|
||||
long start = System.nanoTime();
|
||||
sel.select(5*1000);
|
||||
long waited = (System.nanoTime() - start) / 1000_000;
|
||||
elapsed += waited;
|
||||
buf.clear();
|
||||
SocketAddress sa = dc.receive(buf);
|
||||
|
||||
// no datagram received
|
||||
if (sa == null) {
|
||||
if (datagramExpected) {
|
||||
throw new RuntimeException("Expected message not received");
|
||||
if (elapsed > 4800) {
|
||||
throw new RuntimeException("Expected message not received");
|
||||
} else {
|
||||
sel.selectedKeys().clear();
|
||||
// We haven't waited long enough,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
System.out.println("No message received (correct)");
|
||||
return;
|
||||
@ -121,8 +134,8 @@ public class Promiscuous {
|
||||
int receivedId = -1;
|
||||
try {
|
||||
receivedId = Integer.parseInt(s);
|
||||
System.out.format("Received message from %s (id=0x%x)\n",
|
||||
sender, receivedId);
|
||||
System.out.format("Received message from %s (id=0x%x, length=%s)\n",
|
||||
sender, receivedId, bytes.length);
|
||||
} catch (NumberFormatException x) {
|
||||
System.out.format("Received message from %s (msg=%s)\n", sender, s);
|
||||
}
|
||||
@ -140,7 +153,6 @@ public class Promiscuous {
|
||||
}
|
||||
|
||||
sel.selectedKeys().clear();
|
||||
buf.rewind();
|
||||
}
|
||||
} finally {
|
||||
sel.close();
|
||||
@ -155,13 +167,14 @@ public class Promiscuous {
|
||||
{
|
||||
|
||||
System.out.format("%nTest family=%s%n", family.name());
|
||||
System.out.format("With interface=%s[%s]%n\twith bound addresses:%n\t%s%n",
|
||||
nif.getDisplayName(), nif.getIndex(), nif.inetAddresses().toList());
|
||||
|
||||
DatagramChannel dc1 = (family == UNSPEC) ?
|
||||
DatagramChannel.open() : DatagramChannel.open(family);
|
||||
DatagramChannel dc2 = (family == UNSPEC) ?
|
||||
DatagramChannel.open() : DatagramChannel.open(family);
|
||||
try (DatagramChannel dc1 = (family == UNSPEC) ?
|
||||
DatagramChannel.open() : DatagramChannel.open(family);
|
||||
DatagramChannel dc2 = (family == UNSPEC) ?
|
||||
DatagramChannel.open() : DatagramChannel.open(family)) {
|
||||
|
||||
try {
|
||||
dc1.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
||||
dc2.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
||||
|
||||
@ -184,12 +197,8 @@ public class Promiscuous {
|
||||
|
||||
id = sendDatagram(nif, group2, port);
|
||||
|
||||
receiveDatagram(dc1, "dc1", false, id);
|
||||
receiveDatagram(dc2, "dc2", true, id);
|
||||
|
||||
} finally {
|
||||
dc1.close();
|
||||
dc2.close();
|
||||
receiveDatagram(dc1, "dc1", false, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,10 +27,19 @@
|
||||
* @summary Check that DatagramChannel.receive returns a new SocketAddress
|
||||
* when it receives a packet from the same source address but
|
||||
* different endpoint.
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* ReceiveISA
|
||||
* @run main/othervm ReceiveISA
|
||||
*
|
||||
*/
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
import static java.lang.System.out;
|
||||
|
||||
public class ReceiveISA {
|
||||
@ -44,10 +53,13 @@ public class ReceiveISA {
|
||||
DatagramChannel dc3 = DatagramChannel.open();
|
||||
DatagramChannel dc4 = DatagramChannel.open()) { // client
|
||||
|
||||
dc3.socket().bind((SocketAddress) null); // bind server to any port
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
InetSocketAddress dest = Platform.isOSX()
|
||||
? new InetSocketAddress(lh, 0)
|
||||
: null;
|
||||
dc3.socket().bind(dest); // bind server to any port
|
||||
|
||||
// get server address
|
||||
InetAddress lh = InetAddress.getLocalHost();
|
||||
InetSocketAddress isa = new InetSocketAddress(lh, dc3.socket().getLocalPort());
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(100);
|
||||
|
@ -39,8 +39,8 @@ import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
public class SelectWhenRefused {
|
||||
static final int MAX_TRIES = 3;
|
||||
static final String GREETINGS_MESSAGE = "Greetings from SelectWhenRefused!";
|
||||
static final int MAX_TRIES = 10;
|
||||
static final String GREETINGS_MESSAGE = System.nanoTime() + ": Greetings from SelectWhenRefused!";
|
||||
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
@ -49,9 +49,39 @@ public class SelectWhenRefused {
|
||||
|
||||
// datagram sent to this address should be refused
|
||||
SocketAddress refuser = new InetSocketAddress(InetAddress.getLocalHost(), port);
|
||||
System.err.println("Refuser is: " + refuser);
|
||||
|
||||
DatagramChannel dc = DatagramChannel.open().bind(new InetSocketAddress(0));
|
||||
DatagramChannel dc = null;
|
||||
for (int i=0; i < MAX_TRIES; i++) {
|
||||
dc = DatagramChannel.open();
|
||||
try {
|
||||
dc.bind(new InetSocketAddress(0));
|
||||
} catch (Throwable t) {
|
||||
dc.close();
|
||||
throw t;
|
||||
}
|
||||
|
||||
// check the port assigned to dc
|
||||
if (((InetSocketAddress)dc.getLocalAddress()).getPort() != port) {
|
||||
// We got a good port. Do not retry
|
||||
break;
|
||||
}
|
||||
|
||||
// We bound to the same port that the refuser is using, This will not
|
||||
// work. Retry binding if possible.
|
||||
if (i < MAX_TRIES - 1) {
|
||||
// we will retry...
|
||||
System.err.format("Refuser port has been reused by dc: %s, retrying...%n",
|
||||
dc.getLocalAddress());
|
||||
} else {
|
||||
// that was the last attempt... Skip the test
|
||||
System.err.format("Skipping test: refuser port has been reused by dc: %s%n",
|
||||
dc.getLocalAddress());
|
||||
return;
|
||||
}
|
||||
}
|
||||
dc1.close();
|
||||
assert dc != null;
|
||||
|
||||
Selector sel = Selector.open();
|
||||
try {
|
||||
@ -88,7 +118,7 @@ public class SelectWhenRefused {
|
||||
}
|
||||
} catch (BindException e) {
|
||||
// Do nothing, some other test has used this port
|
||||
System.out.println("Skipping test: refuser port has been reused: " + e);
|
||||
System.err.println("Skipping test: refuser port has been reused: " + e);
|
||||
} finally {
|
||||
sel.close();
|
||||
dc.close();
|
||||
@ -119,7 +149,9 @@ public class SelectWhenRefused {
|
||||
|
||||
// BindException will be thrown if another service is using
|
||||
// our expected refuser port, cannot run just exit.
|
||||
DatagramChannel.open().bind(refuser).close();
|
||||
try (DatagramChannel dc2 = DatagramChannel.open()) {
|
||||
dc2.bind(refuser);
|
||||
}
|
||||
throw new RuntimeException("Unexpected wakeup");
|
||||
}
|
||||
return true; // test passed
|
||||
@ -151,7 +183,7 @@ public class SelectWhenRefused {
|
||||
byte[] bytes = new byte[buf.remaining()];
|
||||
buf.get(bytes);
|
||||
String message = new String(bytes);
|
||||
System.out.format("received %s at %s from %s%n", message, dc.getLocalAddress(), sa);
|
||||
System.err.format("received %s at %s from %s%n", message, dc.getLocalAddress(), sa);
|
||||
|
||||
// If any received data contains the message from sendDatagram then throw exception
|
||||
if (message.contains(GREETINGS_MESSAGE)) {
|
||||
@ -166,10 +198,12 @@ public class SelectWhenRefused {
|
||||
|
||||
// BindException will be thrown if another service is using
|
||||
// our expected refuser port, cannot run just exit.
|
||||
DatagramChannel.open().bind(refuser).close();
|
||||
try (DatagramChannel dc2 = DatagramChannel.open()) {
|
||||
dc2.bind(refuser);
|
||||
}
|
||||
throw new RuntimeException("PortUnreachableException not raised");
|
||||
} catch (PortUnreachableException pue) {
|
||||
System.out.println("Got expected PortUnreachableException " + pue);
|
||||
System.err.println("Got expected PortUnreachableException " + pue);
|
||||
}
|
||||
}
|
||||
return true; // test passed
|
||||
@ -215,16 +249,16 @@ public class SelectWhenRefused {
|
||||
*
|
||||
*/
|
||||
static boolean checkUnexpectedWakeup(Set<SelectionKey> selectedKeys) {
|
||||
System.out.format("Received %d keys%n", selectedKeys.size());
|
||||
System.err.format("Received %d keys%n", selectedKeys.size());
|
||||
|
||||
for (SelectionKey key : selectedKeys) {
|
||||
if (!key.isValid() || !key.isReadable()) {
|
||||
System.out.println("Invalid or unreadable key: " + key);
|
||||
System.err.println("Invalid or unreadable key: " + key);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
System.out.println("Attempting to read datagram from key: " + key);
|
||||
System.err.println("Attempting to read datagram from key: " + key);
|
||||
DatagramChannel datagramChannel = (DatagramChannel) key.channel();
|
||||
ByteBuffer buf = ByteBuffer.allocate(100);
|
||||
SocketAddress sa = datagramChannel.receive(buf);
|
||||
@ -234,7 +268,7 @@ public class SelectWhenRefused {
|
||||
byte[] bytes = new byte[buf.remaining()];
|
||||
buf.get(bytes);
|
||||
String message = new String(bytes);
|
||||
System.out.format("received %s at %s from %s%n", message, datagramChannel.getLocalAddress(), sa);
|
||||
System.err.format("received %s at %s from %s%n", message, datagramChannel.getLocalAddress(), sa);
|
||||
|
||||
// If any received data contains the message from sendDatagram then return false
|
||||
if (message.contains(GREETINGS_MESSAGE)) {
|
||||
@ -243,7 +277,7 @@ public class SelectWhenRefused {
|
||||
}
|
||||
|
||||
} catch (IOException io) {
|
||||
System.out.println("Unable to read from datagram " + io);
|
||||
System.err.println("Unable to read from datagram " + io);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,6 +37,7 @@ import jdk.test.lib.RandomFactory;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
@ -46,6 +47,7 @@ import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.util.ArrayList;
|
||||
@ -139,7 +141,9 @@ public class SendReceiveMaxSize {
|
||||
var addr = new InetSocketAddress(host, port);
|
||||
|
||||
try (var sender = supplier.open()) {
|
||||
sender.bind(null);
|
||||
sender.bind(new InetSocketAddress(host, 0));
|
||||
System.out.format("testSendReceiveMaxSize: sender: %s -> receiver: %s%n",
|
||||
sender.getLocalAddress(), receiver.getLocalAddress());
|
||||
if (!Platform.isOSX()) {
|
||||
if (sender.getOption(SO_SNDBUF) < capacity)
|
||||
sender.setOption(SO_SNDBUF, capacity);
|
||||
@ -150,7 +154,18 @@ public class SendReceiveMaxSize {
|
||||
var sendBuf = ByteBuffer.wrap(testData);
|
||||
sender.send(sendBuf, addr);
|
||||
var receiveBuf = ByteBuffer.allocate(capacity);
|
||||
receiver.receive(receiveBuf);
|
||||
SocketAddress src;
|
||||
int count = 0;
|
||||
do {
|
||||
receiveBuf.clear();
|
||||
src = receiver.receive(receiveBuf);
|
||||
if (sender.getLocalAddress().equals(src)) break;
|
||||
System.out.println("step1: received unexpected datagram from: " + src);
|
||||
System.out.println("\texpected: " + sender.getLocalAddress());
|
||||
if (++count > 10) {
|
||||
throw new AssertionError("too many unexpected messages");
|
||||
}
|
||||
} while (true);
|
||||
|
||||
sendBuf.flip();
|
||||
receiveBuf.flip();
|
||||
@ -167,7 +182,17 @@ public class SendReceiveMaxSize {
|
||||
sendBuf = ByteBuffer.wrap(testData);
|
||||
sender.send(sendBuf, addr);
|
||||
receiveBuf = ByteBuffer.allocate(capacity - 1);
|
||||
receiver.receive(receiveBuf);
|
||||
count = 0;
|
||||
do {
|
||||
receiveBuf.clear();
|
||||
src = receiver.receive(receiveBuf);
|
||||
if (sender.getLocalAddress().equals(src)) break;
|
||||
System.out.println("step1: received unexpected datagram from: " + src);
|
||||
System.out.println("\texpected: " + sender.getLocalAddress());
|
||||
if (++count > 10) {
|
||||
throw new AssertionError("too many unexpected messages");
|
||||
}
|
||||
} while (true);
|
||||
|
||||
sendBuf.flip();
|
||||
receiveBuf.flip();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,6 +24,9 @@
|
||||
/* @test
|
||||
* @bug 4669040 8130394
|
||||
* @summary Test DatagramChannel subsequent receives with no datagram ready
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Platform Sender
|
||||
* @run main Sender
|
||||
* @author Mike McCloskey
|
||||
*/
|
||||
|
||||
@ -36,6 +39,8 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
public class Sender {
|
||||
|
||||
static PrintStream log = System.err;
|
||||
@ -46,25 +51,26 @@ public class Sender {
|
||||
}
|
||||
|
||||
static void test() throws Exception {
|
||||
Server server = new Server();
|
||||
Client client = new Client(server.port());
|
||||
try (Server server = new Server()) {
|
||||
Client client = new Client(server.port());
|
||||
|
||||
Thread serverThread = new Thread(server);
|
||||
serverThread.start();
|
||||
Thread serverThread = new Thread(server);
|
||||
serverThread.start();
|
||||
|
||||
Thread clientThread = new Thread(client);
|
||||
clientThread.start();
|
||||
Thread clientThread = new Thread(client);
|
||||
clientThread.start();
|
||||
|
||||
serverThread.join();
|
||||
clientThread.join();
|
||||
serverThread.join();
|
||||
clientThread.join();
|
||||
|
||||
server.throwException();
|
||||
client.throwException();
|
||||
server.throwException();
|
||||
client.throwException();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Client implements Runnable {
|
||||
final int port;
|
||||
Exception e = null;
|
||||
volatile Exception e = null;
|
||||
|
||||
Client(int port) {
|
||||
this.port = port;
|
||||
@ -76,14 +82,17 @@ public class Sender {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
DatagramChannel dc = DatagramChannel.open();
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(12);
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
bb.putInt(1).putLong(1);
|
||||
bb.flip();
|
||||
InetAddress address = InetAddress.getLocalHost();
|
||||
InetSocketAddress isa = new InetSocketAddress(address, port);
|
||||
if (Platform.isOSX()) {
|
||||
// avoid binding on wildcard on macOS
|
||||
dc.bind(new InetSocketAddress(address, 0));
|
||||
}
|
||||
dc.connect(isa);
|
||||
clientISA = dc.getLocalAddress();
|
||||
dc.write(bb);
|
||||
@ -93,12 +102,16 @@ public class Sender {
|
||||
}
|
||||
}
|
||||
|
||||
public static class Server implements Runnable {
|
||||
public static class Server implements Runnable, AutoCloseable {
|
||||
final DatagramChannel dc;
|
||||
Exception e = null;
|
||||
volatile Exception e = null;
|
||||
|
||||
Server() throws IOException {
|
||||
dc = DatagramChannel.open().bind(new InetSocketAddress(0));
|
||||
// avoid binding to wildcard address on macOS
|
||||
InetSocketAddress lo = Platform.isOSX()
|
||||
? new InetSocketAddress(InetAddress.getLocalHost(), 0)
|
||||
: new InetSocketAddress(0);
|
||||
dc = DatagramChannel.open().bind(lo);
|
||||
}
|
||||
|
||||
int port() {
|
||||
@ -149,6 +162,11 @@ public class Sender {
|
||||
e = ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
dc.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user