diff --git a/core-java-modules/core-java-io-2/pom.xml b/core-java-modules/core-java-io-2/pom.xml
index 0c271737d9..960cc51bbd 100644
--- a/core-java-modules/core-java-io-2/pom.xml
+++ b/core-java-modules/core-java-io-2/pom.xml
@@ -45,6 +45,14 @@
${assertj.version}
test
+
+
+ com.github.tomakehurst
+ wiremock
+ 2.26.3
+ test
+
+
diff --git a/core-java-modules/core-java-io-2/src/test/java/com/baeldung/blockingnonblocking/BlockingClientUnitTest.java b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/blockingnonblocking/BlockingClientUnitTest.java
new file mode 100644
index 0000000000..eca2a2638f
--- /dev/null
+++ b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/blockingnonblocking/BlockingClientUnitTest.java
@@ -0,0 +1,51 @@
+package com.baeldung.blockingnonblocking;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.*;
+import java.net.Socket;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static org.junit.Assert.assertTrue;
+
+public class BlockingClientUnitTest {
+ private static final String REQUESTED_RESOURCE = "/test.json";
+
+ @Rule public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort());
+
+ @Before
+ public void setup() {
+ stubFor(get(urlEqualTo(REQUESTED_RESOURCE)).willReturn(aResponse()
+ .withStatus(200)
+ .withBody("{ \"response\" : \"It worked!\" }\r\n\r\n")));
+ }
+
+ @Test
+ public void givenJavaIOSocket_whenReadingAndWritingWithStreams_thenReadSuccessfully() throws IOException {
+ // given an IO socket and somewhere to store our result
+ Socket socket = new Socket("localhost", wireMockRule.port());
+ StringBuilder ourStore = new StringBuilder();
+
+ // when we write and read (using try-with-resources so our resources are auto-closed)
+ try (InputStream serverInput = socket.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(serverInput));
+ OutputStream clientOutput = socket.getOutputStream();
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientOutput))) {
+ writer.print("GET " + REQUESTED_RESOURCE + " HTTP/1.0\r\n\r\n");
+ writer.flush(); // important - without this the request is never sent, and the test will hang on readLine()
+
+ for (String line; (line = reader.readLine()) != null; ) {
+ ourStore.append(line);
+ }
+ }
+
+ // then we read and saved our data
+ assertTrue(ourStore
+ .toString()
+ .contains("It worked!"));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-io-2/src/test/java/com/baeldung/blockingnonblocking/NonBlockingClientUnitTest.java b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/blockingnonblocking/NonBlockingClientUnitTest.java
new file mode 100644
index 0000000000..47115887ab
--- /dev/null
+++ b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/blockingnonblocking/NonBlockingClientUnitTest.java
@@ -0,0 +1,94 @@
+package com.baeldung.blockingnonblocking;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.SocketChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.StandardCharsets;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static org.junit.Assert.assertTrue;
+
+public class NonBlockingClientUnitTest {
+ private String REQUESTED_RESOURCE = "/test.json";
+
+ @Rule public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort());
+
+ @Before
+ public void setup() {
+ stubFor(get(urlEqualTo(REQUESTED_RESOURCE)).willReturn(aResponse()
+ .withStatus(200)
+ .withBody("{ \"response\" : \"It worked!\" }")));
+ }
+
+ @Test
+ public void givenJavaNIOSocketChannel_whenReadingAndWriting_thenUseBuffers() throws IOException {
+ // given a NIO SocketChannel and a charset
+ InetSocketAddress address = new InetSocketAddress("localhost", wireMockRule.port());
+ SocketChannel socketChannel = SocketChannel.open(address);
+ Charset charset = StandardCharsets.UTF_8;
+
+ // when we write and read using buffers
+ socketChannel.write(charset.encode(CharBuffer.wrap("GET " + REQUESTED_RESOURCE + " HTTP/1.0\r\n\r\n")));
+
+ ByteBuffer buffer = ByteBuffer.allocate(8); // or allocateDirect if we need direct memory access
+ CharBuffer charBuffer = CharBuffer.allocate(8192);
+ CharsetDecoder decoder = charset.newDecoder();
+ StringBuilder ourStore = new StringBuilder();
+ while (socketChannel.read(buffer) != -1 || buffer.position() > 0) {
+ buffer.flip();
+ storeBufferContents(buffer, charBuffer, decoder, ourStore);
+ buffer.compact();
+ }
+ socketChannel.close();
+
+ // then we read and saved our data
+ assertTrue(ourStore
+ .toString()
+ .contains("It worked!"));
+ }
+
+ @Test
+ public void givenJavaNIO_whenReadingAndWriting_thenSmallBuffers() throws IOException {
+ // given a NIO SocketChannel and a charset
+ InetSocketAddress address = new InetSocketAddress("localhost", wireMockRule.port());
+ SocketChannel socket = SocketChannel.open(address);
+ Charset charset = StandardCharsets.UTF_8;
+
+ // when we write and read using buffers that are too small for our message
+ socket.write(charset.encode(CharBuffer.wrap("GET " + REQUESTED_RESOURCE + " HTTP/1.0\r\n\r\n")));
+
+ ByteBuffer buffer = ByteBuffer.allocate(8); // or allocateDirect if we need direct memory access
+ CharBuffer charBuffer = CharBuffer.allocate(8);
+ CharsetDecoder decoder = charset.newDecoder();
+ StringBuilder ourStore = new StringBuilder();
+ while (socket.read(buffer) != -1 || buffer.position() > 0) {
+ buffer.flip();
+ storeBufferContents(buffer, charBuffer, decoder, ourStore);
+ buffer.compact();
+ }
+ socket.close();
+
+ // then we read and saved our data
+ assertTrue(ourStore
+ .toString()
+ .contains("It worked!"));
+ }
+
+ void storeBufferContents(ByteBuffer buffer, CharBuffer charBuffer, CharsetDecoder decoder, StringBuilder ourStore) {
+ decoder.decode(buffer, charBuffer, true);
+ charBuffer.flip();
+ ourStore.append(charBuffer);
+ charBuffer.clear();
+ }
+
+}
\ No newline at end of file