Merge branch 'master' into JAVA-7244-Review_log_statements_for_projects
This commit is contained in:
@@ -9,4 +9,5 @@ This module contains articles about networking in Java
|
||||
- [Connection Timeout vs. Read Timeout for Java Sockets](https://www.baeldung.com/java-socket-connection-read-timeout)
|
||||
- [Find Whether an IP Address Is in the Specified Range or Not in Java](https://www.baeldung.com/java-check-ip-address-range)
|
||||
- [Find the IP Address of a Client Connected to a Server](https://www.baeldung.com/java-client-get-ip-address)
|
||||
- [Unix Domain Socket in Java 16](https://www.baeldung.com/java-unix-domain-socket)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-networking-2)
|
||||
|
||||
@@ -29,21 +29,10 @@
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>${tomcat.embeded.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<version>${javax.mail.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.github.seancfoley/ipaddress -->
|
||||
<dependency>
|
||||
@@ -75,16 +64,26 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>16</source>
|
||||
<target>16</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<spring.core.version>5.2.8.RELEASE</spring.core.version>
|
||||
<jetty.embeded.version>9.4.31.v20200723</jetty.embeded.version>
|
||||
<tomcat.embeded.version>10.0.0-M7</tomcat.embeded.version>
|
||||
<assertj.version>3.11.1</assertj.version>
|
||||
<seancfoley.ipaddress.version>5.3.3</seancfoley.ipaddress.version>
|
||||
<jgonian.commons-ip-math.version>1.32</jgonian.commons-ip-math.version>
|
||||
<googlecode.ipv6.version>0.17</googlecode.ipv6.version>
|
||||
<javax.mail.version>1.6.2</javax.mail.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.socket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.UnixDomainSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.file.Path;
|
||||
|
||||
class UnixDomainSocketClient {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new UnixDomainSocketClient().runClient();
|
||||
}
|
||||
|
||||
void runClient() throws IOException {
|
||||
Path socketPath = Path.of(System.getProperty("user.home"))
|
||||
.resolve("baeldung.socket");
|
||||
UnixDomainSocketAddress socketAddress = getAddress(socketPath);
|
||||
|
||||
SocketChannel channel = openSocketChannel(socketAddress);
|
||||
|
||||
String message = "Hello from Baeldung Unix domain socket article";
|
||||
writeMessage(channel, message);
|
||||
}
|
||||
|
||||
UnixDomainSocketAddress getAddress(Path socketPath) {
|
||||
return UnixDomainSocketAddress.of(socketPath);
|
||||
}
|
||||
|
||||
SocketChannel openSocketChannel(UnixDomainSocketAddress socketAddress) throws IOException {
|
||||
SocketChannel channel = SocketChannel
|
||||
.open(StandardProtocolFamily.UNIX);
|
||||
channel.connect(socketAddress);
|
||||
return channel;
|
||||
}
|
||||
|
||||
void writeMessage(SocketChannel socketChannel, String message) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
buffer.clear();
|
||||
buffer.put(message.getBytes());
|
||||
buffer.flip();
|
||||
|
||||
while (buffer.hasRemaining()) {
|
||||
socketChannel.write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.socket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.UnixDomainSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
class UnixDomainSocketServer {
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
new UnixDomainSocketServer().runServer();
|
||||
}
|
||||
|
||||
void runServer() throws IOException, InterruptedException {
|
||||
Path socketPath = Path.of(System.getProperty("user.home"))
|
||||
.resolve("baeldung.socket");
|
||||
Files.deleteIfExists(socketPath);
|
||||
UnixDomainSocketAddress socketAddress = getAddress(socketPath);
|
||||
|
||||
ServerSocketChannel serverChannel = createServerSocketChannel(socketAddress);
|
||||
|
||||
SocketChannel channel = serverChannel.accept();
|
||||
|
||||
while (true) {
|
||||
readSocketMessage(channel)
|
||||
.ifPresent(message -> System.out.printf("[Client message] %s%n", message));
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
UnixDomainSocketAddress getAddress(Path socketPath) {
|
||||
return UnixDomainSocketAddress.of(socketPath);
|
||||
}
|
||||
|
||||
ServerSocketChannel createServerSocketChannel(UnixDomainSocketAddress socketAddress) throws IOException {
|
||||
ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
|
||||
serverChannel.bind(socketAddress);
|
||||
return serverChannel;
|
||||
}
|
||||
|
||||
Optional<String> readSocketMessage(SocketChannel channel) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
int bytesRead = channel.read(buffer);
|
||||
if (bytesRead < 0) return Optional.empty();
|
||||
byte[] bytes = new byte[bytesRead];
|
||||
buffer.flip();
|
||||
buffer.get(bytes);
|
||||
String message = new String(bytes);
|
||||
return Optional.of(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,36 +4,26 @@ import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
public class FindFreePortUnitTest {
|
||||
|
||||
private static int FREE_PORT_NUMBER;
|
||||
private static int[] FREE_PORT_RANGE;
|
||||
|
||||
@BeforeAll
|
||||
public static void getExplicitFreePortNumberAndRange() {
|
||||
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||
FREE_PORT_NUMBER = serverSocket.getLocalPort();
|
||||
FREE_PORT_RANGE = new int[] {FREE_PORT_NUMBER, FREE_PORT_NUMBER + 1, FREE_PORT_NUMBER + 2};
|
||||
} catch (IOException e) {
|
||||
fail("No free port is available");
|
||||
}
|
||||
}
|
||||
private static final int DEFAULT_RANDOM_PORT = 34307;
|
||||
|
||||
@Test
|
||||
public void givenExplicitFreePort_whenCreatingServerSocket_thenThatPortIsAssigned() {
|
||||
try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) {
|
||||
int freePort = getFreePort();
|
||||
|
||||
try (ServerSocket serverSocket = new ServerSocket(freePort)) {
|
||||
assertThat(serverSocket).isNotNull();
|
||||
assertThat(serverSocket.getLocalPort()).isEqualTo(FREE_PORT_NUMBER);
|
||||
assertThat(serverSocket.getLocalPort()).isEqualTo(freePort);
|
||||
} catch (IOException e) {
|
||||
fail("Port is not available");
|
||||
}
|
||||
@@ -41,8 +31,10 @@ public class FindFreePortUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenExplicitOccupiedPort_whenCreatingServerSocket_thenExceptionIsThrown() {
|
||||
try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) {
|
||||
new ServerSocket(FREE_PORT_NUMBER);
|
||||
int freePort = getFreePort();
|
||||
|
||||
try (ServerSocket serverSocket = new ServerSocket(freePort)) {
|
||||
new ServerSocket(freePort);
|
||||
fail("Same port cannot be used twice");
|
||||
} catch (IOException e) {
|
||||
assertThat(e).hasMessageContaining("Address already in use");
|
||||
@@ -51,7 +43,7 @@ public class FindFreePortUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenExplicitPortRange_whenCreatingServerSocket_thenOnePortIsAssigned() {
|
||||
for (int port : FREE_PORT_RANGE) {
|
||||
for (int port : getFreePorts()) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(port)) {
|
||||
assertThat(serverSocket).isNotNull();
|
||||
assertThat(serverSocket.getLocalPort()).isEqualTo(port);
|
||||
@@ -104,11 +96,12 @@ public class FindFreePortUnitTest {
|
||||
public void givenExplicitFreePort_whenCreatingJettyServer_thenThatPortIsAssigned() throws Exception {
|
||||
Server jettyServer = new Server();
|
||||
ServerConnector serverConnector = new ServerConnector(jettyServer);
|
||||
serverConnector.setPort(FREE_PORT_NUMBER);
|
||||
int freePort = getFreePort();
|
||||
serverConnector.setPort(freePort);
|
||||
jettyServer.addConnector(serverConnector);
|
||||
try {
|
||||
jettyServer.start();
|
||||
assertThat(serverConnector.getLocalPort()).isEqualTo(FREE_PORT_NUMBER);
|
||||
assertThat(serverConnector.getLocalPort()).isEqualTo(freePort);
|
||||
} catch (Exception e) {
|
||||
fail("Failed to start Jetty server");
|
||||
} finally {
|
||||
@@ -135,10 +128,11 @@ public class FindFreePortUnitTest {
|
||||
@Test
|
||||
public void givenExplicitFreePort_whenCreatingTomcatServer_thenThatPortIsAssigned() throws Exception {
|
||||
Tomcat tomcatServer = new Tomcat();
|
||||
tomcatServer.setPort(FREE_PORT_NUMBER);
|
||||
int freePort = getFreePort();
|
||||
tomcatServer.setPort(freePort);
|
||||
try {
|
||||
tomcatServer.start();
|
||||
assertThat(tomcatServer.getConnector().getLocalPort()).isEqualTo(FREE_PORT_NUMBER);
|
||||
assertThat(tomcatServer.getConnector().getLocalPort()).isEqualTo(freePort);
|
||||
} catch (LifecycleException e) {
|
||||
fail("Failed to start Tomcat server");
|
||||
} finally {
|
||||
@@ -147,4 +141,16 @@ public class FindFreePortUnitTest {
|
||||
}
|
||||
}
|
||||
|
||||
private int[] getFreePorts() {
|
||||
int freePort = getFreePort();
|
||||
return new int[]{freePort - 1, freePort, freePort + 1};
|
||||
}
|
||||
|
||||
private int getFreePort() {
|
||||
try(ServerSocket serverSocket = new ServerSocket(0)){
|
||||
return serverSocket.getLocalPort();
|
||||
} catch (IOException ex){
|
||||
return DEFAULT_RANDOM_PORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.baeldung.socket;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.UnixDomainSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.nio.file.Files.deleteIfExists;
|
||||
import static org.assertj.core.util.Files.newTemporaryFile;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class UnixDomainSocketClientUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSocketPath_shouldCreateUnixDomainSocketAddress() {
|
||||
// given
|
||||
File tempFile = newTemporaryFile();
|
||||
Path socketPath = tempFile.toPath();
|
||||
|
||||
// when
|
||||
UnixDomainSocketAddress address = new UnixDomainSocketClient().getAddress(socketPath);
|
||||
|
||||
// then
|
||||
assertEquals(address.getPath(), socketPath);
|
||||
|
||||
// cleanup
|
||||
tempFile.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnixDomainSocketAddress_shouldOpenSocketChannel() throws IOException {
|
||||
// given
|
||||
File tempFile = newTemporaryFile();
|
||||
Path socketPath = tempFile.toPath();
|
||||
deleteIfExists(socketPath);
|
||||
UnixDomainSocketAddress address = UnixDomainSocketAddress.of(socketPath);
|
||||
|
||||
// bind address as a unix domain socket
|
||||
ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
|
||||
serverChannel.bind(address);
|
||||
|
||||
// when
|
||||
SocketChannel socketChannel = new UnixDomainSocketClient().openSocketChannel(address);
|
||||
|
||||
// then
|
||||
assertTrue(socketChannel.isOpen());
|
||||
assertEquals(socketChannel.getRemoteAddress(), address);
|
||||
|
||||
// cleanup
|
||||
tempFile.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSocketChannelAndMessage_shouldWriteMessage() throws IOException {
|
||||
// given
|
||||
SocketChannel socketChannel = Mockito.mock(SocketChannel.class);
|
||||
String message = UUID.randomUUID().toString();
|
||||
Mockito.when(socketChannel.write(Mockito.any(ByteBuffer.class)))
|
||||
.thenAnswer(
|
||||
(Answer<Integer>) invocationOnMock -> {
|
||||
((ByteBuffer) invocationOnMock.getArguments()[0]).position(message.getBytes().length);
|
||||
return -1;
|
||||
}
|
||||
);
|
||||
|
||||
// when
|
||||
new UnixDomainSocketClient().writeMessage(socketChannel, message);
|
||||
|
||||
// then
|
||||
Mockito.verify(socketChannel, Mockito.times(1)).write(Mockito.any(ByteBuffer.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.socket;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.UnixDomainSocketAddress;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static java.nio.file.Files.deleteIfExists;
|
||||
import static org.assertj.core.util.Files.newTemporaryFile;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class UnixDomainSocketServerUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSocketPath_shouldCreateUnixDomainSocketAddress() {
|
||||
// given
|
||||
File tempFile = newTemporaryFile();
|
||||
Path socketPath = tempFile.toPath();
|
||||
|
||||
// when
|
||||
UnixDomainSocketAddress address = new UnixDomainSocketServer().getAddress(socketPath);
|
||||
|
||||
// then
|
||||
assertEquals(address.getPath(), socketPath);
|
||||
|
||||
// cleanup
|
||||
tempFile.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnixDomainSocketAddress_shouldCreateServerSocketChannel() throws IOException {
|
||||
// given
|
||||
File tempFile = newTemporaryFile();
|
||||
Path socketPath = tempFile.toPath();
|
||||
deleteIfExists(socketPath);
|
||||
UnixDomainSocketAddress address = UnixDomainSocketAddress.of(socketPath);
|
||||
|
||||
// when
|
||||
ServerSocketChannel serverSocketChannel = new UnixDomainSocketServer().createServerSocketChannel(address);
|
||||
|
||||
// then
|
||||
assertEquals(serverSocketChannel.getLocalAddress(), address);
|
||||
|
||||
// cleanup
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user