21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 /** |
24 /** |
25 * @test |
25 * @test |
26 * @run main UdpSocket |
26 * @run testng/othervm -Dsun.net.maxDatagramSockets=32 UdpSocket |
27 * @summary Basic test for a Socket to a UDP socket |
27 * @summary Basic test for a Socket to a UDP socket |
28 */ |
28 */ |
29 |
29 |
30 import java.io.IOException; |
30 import java.io.IOException; |
|
31 import java.lang.ref.WeakReference; |
31 import java.net.InetAddress; |
32 import java.net.InetAddress; |
32 import java.net.InetSocketAddress; |
33 import java.net.InetSocketAddress; |
33 import java.net.Socket; |
34 import java.net.Socket; |
34 import java.net.SocketAddress; |
35 import java.net.SocketAddress; |
35 import java.nio.ByteBuffer; |
36 import java.nio.ByteBuffer; |
36 import java.nio.channels.DatagramChannel; |
37 import java.nio.channels.DatagramChannel; |
|
38 import java.security.Permission; |
37 import java.util.Arrays; |
39 import java.util.Arrays; |
|
40 import java.util.ArrayList; |
|
41 import java.util.ArrayDeque; |
|
42 import java.util.Deque; |
38 |
43 |
|
44 import org.testng.annotations.Test; |
|
45 import static org.testng.Assert.*; |
|
46 |
|
47 @Test |
39 public class UdpSocket { |
48 public class UdpSocket { |
40 |
49 |
41 static final String MESSAGE = "hello"; |
50 /** |
|
51 * Test using the Socket API to send/receive datagrams |
|
52 */ |
|
53 public void testSendReceive() throws IOException { |
|
54 final String MESSAGE = "hello"; |
42 |
55 |
43 public static void main(String[] args) throws IOException { |
|
44 try (DatagramChannel dc = DatagramChannel.open()) { |
56 try (DatagramChannel dc = DatagramChannel.open()) { |
45 var loopback = InetAddress.getLoopbackAddress(); |
57 var loopback = InetAddress.getLoopbackAddress(); |
46 dc.bind(new InetSocketAddress(loopback, 0)); |
58 dc.bind(new InetSocketAddress(loopback, 0)); |
47 |
59 |
48 int port = ((InetSocketAddress) dc.getLocalAddress()).getPort(); |
60 int port = ((InetSocketAddress) dc.getLocalAddress()).getPort(); |
54 |
66 |
55 // receive the datagram |
67 // receive the datagram |
56 var buf = ByteBuffer.allocate(100); |
68 var buf = ByteBuffer.allocate(100); |
57 SocketAddress remote = dc.receive(buf); |
69 SocketAddress remote = dc.receive(buf); |
58 buf.flip(); |
70 buf.flip(); |
59 if (buf.remaining() != MESSAGE.length()) |
71 assertTrue(buf.remaining() == MESSAGE.length(), "Unexpected size"); |
60 throw new RuntimeException("Unexpected size"); |
|
61 |
72 |
62 // echo the datagram |
73 // echo the datagram |
63 dc.send(buf, remote); |
74 dc.send(buf, remote); |
64 |
75 |
65 // receive datagram with the socket input stream |
76 // receive datagram with the socket input stream |
66 byte[] array2 = new byte[100]; |
77 byte[] array2 = new byte[100]; |
67 int n = s.getInputStream().read(array2); |
78 int n = s.getInputStream().read(array2); |
68 if (n != MESSAGE.length()) |
79 assertTrue(n == MESSAGE.length(), "Unexpected size"); |
69 throw new RuntimeException("Unexpected size"); |
80 assertEquals(Arrays.copyOf(array1, n), Arrays.copyOf(array2, n), |
70 if (!Arrays.equals(array1, 0, n, array2, 0, n)) |
81 "Unexpected contents"); |
71 throw new RuntimeException("Unexpected contents"); |
|
72 } |
82 } |
73 } |
83 } |
74 } |
84 } |
|
85 |
|
86 /** |
|
87 * Test that the number of UDP sockets is limited when running with a |
|
88 * security manager. |
|
89 */ |
|
90 public void testMaxSockets() throws Exception { |
|
91 int limit = Integer.getInteger("sun.net.maxDatagramSockets"); |
|
92 |
|
93 // security manager grants all permissions |
|
94 var securityManager = new SecurityManager() { |
|
95 @Override public void checkPermission(Permission perm) { } |
|
96 }; |
|
97 |
|
98 System.setSecurityManager(securityManager); |
|
99 Deque<Socket> sockets = new ArrayDeque<>(); |
|
100 try { |
|
101 // create the maximum number of sockets |
|
102 for (int i=0; i<limit; i++) { |
|
103 sockets.offer(newUdpSocket()); |
|
104 } |
|
105 |
|
106 // try to create another socket - should fail |
|
107 try { |
|
108 Socket s = newUdpSocket(); |
|
109 s.close(); |
|
110 assertTrue(false); |
|
111 } catch (IOException expected) { } |
|
112 |
|
113 // close one socket |
|
114 sockets.pop().close(); |
|
115 |
|
116 // try to create another socket - should succeed |
|
117 Socket s = newUdpSocket(); |
|
118 |
|
119 // unreference the socket and wait for it to be closed by the cleaner |
|
120 var ref = new WeakReference<>(s); |
|
121 s = null; |
|
122 while (ref.get() != null) { |
|
123 System.gc(); |
|
124 Thread.sleep(100); |
|
125 } |
|
126 |
|
127 // try to create another socket - should succeed |
|
128 s = newUdpSocket(); |
|
129 s.close(); |
|
130 } finally { |
|
131 closeAll(sockets); |
|
132 System.setSecurityManager(null); |
|
133 } |
|
134 } |
|
135 |
|
136 private Socket newUdpSocket() throws IOException { |
|
137 return new Socket(InetAddress.getLoopbackAddress(), 8000, false); |
|
138 } |
|
139 |
|
140 private void closeAll(Deque<Socket> sockets) throws IOException { |
|
141 Socket s; |
|
142 while ((s = sockets.poll()) != null) { |
|
143 s.close(); |
|
144 } |
|
145 } |
75 } |
146 } |