48 import java.nio.file.Path; |
48 import java.nio.file.Path; |
49 import java.nio.file.Paths; |
49 import java.nio.file.Paths; |
50 import java.util.ArrayDeque; |
50 import java.util.ArrayDeque; |
51 import java.util.List; |
51 import java.util.List; |
52 import java.util.Optional; |
52 import java.util.Optional; |
|
53 import java.util.concurrent.Phaser; |
53 import java.util.concurrent.TimeUnit; |
54 import java.util.concurrent.TimeUnit; |
54 |
55 |
55 import jdk.test.lib.net.IPSupport; |
56 import jdk.test.lib.net.IPSupport; |
56 |
57 |
57 import com.sun.management.UnixOperatingSystemMXBean; |
58 import com.sun.management.UnixOperatingSystemMXBean; |
70 |
71 |
71 // Server to echo a datagram packet |
72 // Server to echo a datagram packet |
72 static class Server implements Runnable { |
73 static class Server implements Runnable { |
73 |
74 |
74 MulticastSocket ss; |
75 MulticastSocket ss; |
75 |
76 final int port; |
|
77 final Phaser phaser = new Phaser(2); |
76 Server() throws IOException { |
78 Server() throws IOException { |
|
79 InetAddress loopback = InetAddress.getLoopbackAddress(); |
77 InetSocketAddress serverAddress = |
80 InetSocketAddress serverAddress = |
78 new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); |
81 new InetSocketAddress(loopback, 0); |
79 ss = new MulticastSocket(serverAddress); |
82 ss = new MulticastSocket(serverAddress); |
|
83 port = ss.getLocalPort(); |
80 System.out.printf(" DatagramServer addr: %s: %d%n", |
84 System.out.printf(" DatagramServer addr: %s: %d%n", |
81 this.getHost(), this.getPort()); |
85 this.getHost(), this.getPort()); |
82 pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverMulticastSocket")); |
86 pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverMulticastSocket")); |
83 extractRefs(ss, "serverMulticastSocket"); |
87 extractRefs(ss, "serverMulticastSocket"); |
84 } |
88 } |
87 InetAddress localhost = InetAddress.getLoopbackAddress(); |
91 InetAddress localhost = InetAddress.getLoopbackAddress(); |
88 return localhost; |
92 return localhost; |
89 } |
93 } |
90 |
94 |
91 int getPort() { |
95 int getPort() { |
92 return ss.getLocalPort(); |
96 return port; |
93 } |
97 } |
94 |
98 |
95 // Receive a byte and send back a byte |
99 // Receive a byte and send back a byte |
96 public void run() { |
100 public void run() { |
97 try { |
101 try { |
98 byte[] buffer = new byte[50]; |
102 byte[] buffer = new byte[50]; |
99 DatagramPacket p = new DatagramPacket(buffer, buffer.length); |
103 DatagramPacket p = new DatagramPacket(buffer, buffer.length); |
100 ss.receive(p); |
104 ss.receive(p); |
|
105 System.out.printf("Server: ping received from: %s%n", p.getSocketAddress()); |
|
106 phaser.arriveAndAwaitAdvance(); // await the client... |
101 buffer[0] += 1; |
107 buffer[0] += 1; |
|
108 System.out.printf("Server: sending echo to: %s%n", p.getSocketAddress()); |
102 ss.send(p); // send back +1 |
109 ss.send(p); // send back +1 |
103 |
110 |
|
111 System.out.printf("Server: awaiting client%n"); |
|
112 phaser.arriveAndAwaitAdvance(); // await the client... |
104 // do NOT close but 'forget' the socket reference |
113 // do NOT close but 'forget' the socket reference |
|
114 System.out.printf("Server: forgetting socket...%n"); |
105 ss = null; |
115 ss = null; |
106 } catch (Exception ioe) { |
116 } catch (Throwable ioe) { |
107 ioe.printStackTrace(); |
117 ioe.printStackTrace(); |
108 } |
118 } |
109 } |
119 } |
110 } |
120 } |
111 |
121 |
112 public static void main(String args[]) throws Exception { |
122 public static void main(String args[]) throws Exception { |
113 IPSupport.throwSkippedExceptionIfNonOperational(); |
123 IPSupport.throwSkippedExceptionIfNonOperational(); |
114 |
124 |
|
125 InetSocketAddress clientAddress = |
|
126 new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); |
|
127 |
115 // Create and close a MulticastSocket to warm up the FD count for side effects. |
128 // Create and close a MulticastSocket to warm up the FD count for side effects. |
116 try (MulticastSocket s = new MulticastSocket(0)) { |
129 try (MulticastSocket s = new MulticastSocket(clientAddress)) { |
117 // no-op; close immediately |
130 // no-op; close immediately |
118 s.getLocalPort(); // no-op |
131 s.getLocalPort(); // no-op |
119 } |
132 } |
120 |
133 |
121 long fdCount0 = getFdCount(); |
134 long fdCount0 = getFdCount(); |
124 // start a server |
137 // start a server |
125 Server svr = new Server(); |
138 Server svr = new Server(); |
126 Thread thr = new Thread(svr); |
139 Thread thr = new Thread(svr); |
127 thr.start(); |
140 thr.start(); |
128 |
141 |
129 MulticastSocket client = new MulticastSocket(0); |
142 // It is possible under some circumstances that the client |
130 System.out.printf(" client bound port: %d%n", client.getLocalPort()); |
143 // might get bound to the same port than the server: this |
|
144 // would make the test fail - so if this happen we try to |
|
145 // bind to a specific port by incrementing the server port. |
|
146 MulticastSocket client = null; |
|
147 int serverPort = svr.getPort(); |
|
148 int maxtries = 20; |
|
149 for (int i = 0; i < maxtries; i++) { |
|
150 try { |
|
151 System.out.printf("Trying to bind client to: %s%n", clientAddress); |
|
152 client = new MulticastSocket(clientAddress); |
|
153 if (client.getLocalPort() != svr.getPort()) break; |
|
154 client.close(); |
|
155 } catch (IOException x) { |
|
156 System.out.printf("Couldn't create client after %d attempts: %s%n", i, x); |
|
157 if (i == maxtries) throw x; |
|
158 } |
|
159 if (i == maxtries) { |
|
160 String msg = String.format("Couldn't create client after %d attempts", i); |
|
161 System.out.println(msg); |
|
162 throw new AssertionError(msg); |
|
163 } |
|
164 clientAddress = new InetSocketAddress(clientAddress.getAddress(), serverPort + i); |
|
165 } |
|
166 |
|
167 System.out.printf(" client bound port: %s:%d%n", |
|
168 client.getLocalAddress(), client.getLocalPort()); |
131 client.connect(svr.getHost(), svr.getPort()); |
169 client.connect(svr.getHost(), svr.getPort()); |
132 pendingSockets.add(new NamedWeak(client, pendingQueue, "clientMulticastSocket")); |
170 pendingSockets.add(new NamedWeak(client, pendingQueue, "clientMulticastSocket")); |
133 extractRefs(client, "clientMulticastSocket"); |
171 extractRefs(client, "clientMulticastSocket"); |
134 |
172 |
135 byte[] msg = new byte[1]; |
173 byte[] msg = new byte[1]; |
136 msg[0] = 1; |
174 msg[0] = 1; |
137 DatagramPacket p = new DatagramPacket(msg, msg.length, svr.getHost(), svr.getPort()); |
175 DatagramPacket p = new DatagramPacket(msg, msg.length, svr.getHost(), svr.getPort()); |
138 client.send(p); |
176 client.send(p); |
|
177 System.out.printf(" ping sent to: %s:%d%n", svr.getHost(), svr.getPort()); |
|
178 svr.phaser.arriveAndAwaitAdvance(); // wait until the server has received its packet |
139 |
179 |
140 p = new DatagramPacket(msg, msg.length); |
180 p = new DatagramPacket(msg, msg.length); |
141 client.receive(p); |
181 client.receive(p); |
142 |
182 |
143 System.out.printf("echo received from: %s%n", p.getSocketAddress()); |
183 System.out.printf(" echo received from: %s%n", p.getSocketAddress()); |
144 if (msg[0] != 2) { |
184 if (msg[0] != 2) { |
145 throw new AssertionError("incorrect data received: expected: 2, actual: " + msg[0]); |
185 throw new AssertionError("incorrect data received: expected: 2, actual: " + msg[0]); |
146 } |
186 } |
|
187 svr.phaser.arriveAndAwaitAdvance(); // let the server null out its socket |
147 |
188 |
148 // Do NOT close the MulticastSocket; forget it |
189 // Do NOT close the MulticastSocket; forget it |
149 |
190 |
150 Object ref; |
191 Object ref; |
151 int loops = 20; |
192 int loops = 20; |