提交 37500321 编写于 作者: A alanb

6621689: (dc spec) DatagramChannel.receive when channel is not bound is not specified

Reviewed-by: sherman
上级 64f7a646
...@@ -261,7 +261,10 @@ public abstract class DatagramChannel ...@@ -261,7 +261,10 @@ public abstract class DatagramChannel
* *
* <p> This method may be invoked at any time. It will not have any effect * <p> This method may be invoked at any time. It will not have any effect
* on read or write operations that are already in progress at the moment * on read or write operations that are already in progress at the moment
* that it is invoked. </p> * that it is invoked. If this channel's socket is not bound then this method
* will first cause the socket to be bound to an address that is assigned
* automatically, as if invoking the {@link #bind bind} method with a
* parameter of {@code null}. </p>
* *
* @param remote * @param remote
* The remote address to which this channel is to be connected * The remote address to which this channel is to be connected
...@@ -356,7 +359,10 @@ public abstract class DatagramChannel ...@@ -356,7 +359,10 @@ public abstract class DatagramChannel
* <p> This method may be invoked at any time. If another thread has * <p> This method may be invoked at any time. If another thread has
* already initiated a read operation upon this channel, however, then an * already initiated a read operation upon this channel, however, then an
* invocation of this method will block until the first operation is * invocation of this method will block until the first operation is
* complete. </p> * complete. If this channel's socket is not bound then this method will
* first cause the socket to be bound to an address that is assigned
* automatically, as if invoking the {@link #bind bind} method with a
* parameter of {@code null}. </p>
* *
* @param dst * @param dst
* The buffer into which the datagram is to be transferred * The buffer into which the datagram is to be transferred
...@@ -413,7 +419,10 @@ public abstract class DatagramChannel ...@@ -413,7 +419,10 @@ public abstract class DatagramChannel
* <p> This method may be invoked at any time. If another thread has * <p> This method may be invoked at any time. If another thread has
* already initiated a write operation upon this channel, however, then an * already initiated a write operation upon this channel, however, then an
* invocation of this method will block until the first operation is * invocation of this method will block until the first operation is
* complete. </p> * complete. If this channel's socket is not bound then this method will
* first cause the socket to be bound to an address that is assigned
* automatically, as if by invoking the {@link #bind bind) method with a
* parameter of {@code null}. </p>
* *
* @param src * @param src
* The buffer containing the datagram to be sent * The buffer containing the datagram to be sent
......
...@@ -313,11 +313,9 @@ class DatagramChannelImpl ...@@ -313,11 +313,9 @@ class DatagramChannelImpl
throw new NullPointerException(); throw new NullPointerException();
synchronized (readLock) { synchronized (readLock) {
ensureOpen(); ensureOpen();
// If socket is not bound then behave as if nothing received // Socket was not bound before attempting receive
// Will be fixed by 6621699 if (localAddress() == null)
if (localAddress() == null) { bind(null);
return null;
}
int n = 0; int n = 0;
ByteBuffer bb = null; ByteBuffer bb = null;
try { try {
......
...@@ -22,27 +22,110 @@ ...@@ -22,27 +22,110 @@
*/ */
/* @test /* @test
* @bug 4512723 * @bug 4512723 6621689
* @summary Unit test for datagram-socket-channel adaptors * @summary Test that connect/send/receive with unbound DatagramChannel causes
* the channel's socket to be bound to a local address
*/ */
import java.net.*; import java.net.*;
import java.nio.*; import java.nio.ByteBuffer;
import java.nio.channels.*; import java.nio.channels.DatagramChannel;
import java.io.IOException;
class NotBound { public class NotBound {
public static void main(String[] args) throws Exception {
test1(false); static void checkBound(DatagramChannel dc) throws IOException {
test1(true); if (dc.getLocalAddress() == null)
throw new RuntimeException("Not bound??");
}
// starts a thread to send a datagram to the given channel once the channel
// is bound to a local address
static void wakeupWhenBound(final DatagramChannel dc) {
Runnable wakeupTask = new Runnable() {
public void run() {
try {
// poll for local address
InetSocketAddress local;
do {
Thread.sleep(50);
local = (InetSocketAddress)dc.getLocalAddress();
} while (local == null);
// 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();
}
} catch (Exception x) {
x.printStackTrace();
}
}};
new Thread(wakeupTask).start();
} }
static void test1(boolean blocking) throws Exception { public static void main(String[] args) throws IOException {
ByteBuffer bb = ByteBuffer.allocateDirect(256); DatagramChannel dc;
DatagramChannel dc1 = DatagramChannel.open();
dc1.configureBlocking(false); // connect
SocketAddress isa = dc1.receive(bb); dc = DatagramChannel.open();
if (isa != null) try {
throw new Exception("Unbound dc returned non-null"); DatagramChannel peer = DatagramChannel.open()
dc1.close(); .bind(new InetSocketAddress(0));
int peerPort = ((InetSocketAddress)(peer.getLocalAddress())).getPort();
try {
dc.connect(new InetSocketAddress(InetAddress.getLocalHost(), peerPort));
checkBound(dc);
} finally {
peer.close();
}
} finally {
dc.close();
}
// send
dc = DatagramChannel.open();
try {
ByteBuffer bb = ByteBuffer.wrap("ignore this".getBytes());
SocketAddress target =
new InetSocketAddress(InetAddress.getLocalHost(), 5000);
dc.send(bb, target);
checkBound(dc);
} finally {
dc.close();
}
// receive (blocking)
dc = DatagramChannel.open();
try {
ByteBuffer bb = ByteBuffer.allocateDirect(128);
wakeupWhenBound(dc);
SocketAddress sender = dc.receive(bb);
if (sender == null)
throw new RuntimeException("Sender should not be null");
checkBound(dc);
} finally {
dc.close();
}
// receive (non-blocking)
dc = DatagramChannel.open();
try {
dc.configureBlocking(false);
ByteBuffer bb = ByteBuffer.allocateDirect(128);
SocketAddress sender = dc.receive(bb);
if (sender != null)
throw new RuntimeException("Sender should be null");
checkBound(dc);
} finally {
dc.close();
}
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册