这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions core-java-modules/core-java-sockets/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-sockets</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>core-java-sockets</name>

<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.baeldung.threading;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;

public class ClientConnection implements Closeable {

private final Socket socket;
private final BufferedReader reader;
private final PrintWriter writer;

public ClientConnection(Socket socket) throws IOException {
this.socket = socket;
this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.writer = new PrintWriter(socket.getOutputStream(), true);
}

public Socket getSocket() {
return socket;
}

public BufferedReader getReader() {
return reader;
}

public PrintWriter getWriter() {
return writer;
}

@Override
public void close() throws IOException {
try (Writer writer = this.writer; Reader reader = this.reader; Socket socket = this.socket) {
// resources all closed when this block exits
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.baeldung.threading.connection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baeldung.threading.ClientConnection;

public class ThreadPerConnection extends Thread {

private static final Logger logger = LoggerFactory.getLogger(ThreadPerConnection.class);

private final ClientConnection clientConnection;

public ThreadPerConnection(ClientConnection clientConnection) {
this.clientConnection = clientConnection;
}

@Override
public void run() {
try (ClientConnection client = this.clientConnection) {
String request;
while ((request = client.getReader()
.readLine()) != null) {
Thread.sleep(1000); // simulate server doing work
logger.info("Processing request: {}", request);
clientConnection.getWriter()
.println("HTTP/1.1 200 OK - Processed request: " + request);
logger.info("Processed request: {}", request);
}
} catch (Exception e) {
logger.error("Error processing request", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.baeldung.threading.connection;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baeldung.threading.ClientConnection;

public class ThreadPerConnectionServer {

private static final Logger logger = LoggerFactory.getLogger(ThreadPerConnectionServer.class);

private static final int PORT = 8080;

public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
logger.info("Server started on port {}", PORT);
while (!serverSocket.isClosed()) {
try {
Socket newClient = serverSocket.accept();
logger.info("New client connected: {}", newClient.getInetAddress());
ClientConnection clientConnection = new ClientConnection(newClient);
new ThreadPerConnection(clientConnection).start();
} catch (IOException e) {
logger.error("Error accepting connection", e);
}
}
} catch (IOException e) {
logger.error("Error starting server", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.baeldung.threading.request;

import java.io.PrintWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ThreadPerRequest extends Thread {

private static final Logger logger = LoggerFactory.getLogger(ThreadPerRequest.class);

private final PrintWriter writer;
private final String request;

public ThreadPerRequest(PrintWriter writer, String request) {
this.writer = writer;
this.request = request;
}

@Override
public void run() {
try {
Thread.sleep(1000); // simulate server doing work
logger.info("Processing request: {}", request);
writer.println("HTTP/1.1 200 OK - Processed request: " + request);
logger.info("Processed request: {}", request);
} catch (Exception e) {
logger.error("Error processing request", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.baeldung.threading.request;

import java.io.BufferedReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baeldung.threading.ClientConnection;

public class ThreadPerRequestServer {

private static final Logger logger = LoggerFactory.getLogger(ThreadPerRequestServer.class);
private static final int PORT = 8080;

public static void main(String[] args) {
List<ClientConnection> clientConnections = new ArrayList<>();

try (ServerSocket serverSocket = new ServerSocket(PORT)) {
logger.info("Server started on port {}", PORT);

while (!serverSocket.isClosed()) {
acceptNewConnections(serverSocket, clientConnections);
handleRequests(clientConnections);
}

} catch (IOException e) {
logger.error("Server error", e);
} finally {
closeClientConnection(clientConnections);
}
}

private static void acceptNewConnections(ServerSocket serverSocket, List<ClientConnection> clientConnections) throws SocketException {
serverSocket.setSoTimeout(100);
try {
Socket newClient = serverSocket.accept();
ClientConnection clientConnection = new ClientConnection(newClient);
clientConnections.add(clientConnection);
logger.info("New client connected: {}", newClient.getInetAddress());
} catch (IOException ignored) {
// ignore expected socket timeout
}
}

private static void handleRequests(List<ClientConnection> clientConnections) {
Iterator<ClientConnection> iterator = clientConnections.iterator();
while (iterator.hasNext()) {
ClientConnection client = iterator.next();

if (client.getSocket()
.isClosed()) {
logger.info("Client disconnected: {}", client.getSocket()
.getInetAddress());
iterator.remove();
continue;
}

try {
BufferedReader reader = client.getReader();
if (reader.ready()) {
String request = reader.readLine();
if (request != null) {
new ThreadPerRequest(client.getWriter(), request).start();
}
}
} catch (IOException e) {
logger.error("Error reading from client {}", client.getSocket()
.getInetAddress(), e);
}
}
}

private static void closeClientConnection(List<ClientConnection> clientConnections) {
for (ClientConnection client : clientConnections) {
try {
client.close();
} catch (IOException e) {
logger.error("Error closing client connection", e);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.baeldung.threading;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

// Note: ThreadPerConnectionServer or ThreadPerRequestServer needs to be started externally in order to execute this test.
class ThreadModelManualTest {

private static final String HOST = "localhost";
private static final int PORT = 8080;

@Test
void whenSendingRequestWithDifferentConnections_thenResponseReceived() throws IOException {
for (int i = 1; i <= 3; i++) {
try (Socket socket = new Socket(HOST, PORT);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String request = "Request " + i;
writer.println(request);
String response = reader.readLine();
Assertions.assertEquals("HTTP/1.1 200 OK - Processed request: " + request, response);
}
}
}

@Test
void whenSendingRequestWithSameConnection_thenResponseReceived() throws IOException, InterruptedException {
try (Socket socket = new Socket(HOST, PORT);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
for (int i = 1; i <= 3; i++) {
String request = "Request " + i;
writer.println(request);
Thread.sleep(2000); // simulate gap between client requests
String response = reader.readLine();

Assertions.assertEquals("HTTP/1.1 200 OK - Processed request: " + request, response);
}
}
}
}
1 change: 1 addition & 0 deletions core-java-modules/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
<module>core-java-security-5</module>
<module>core-java-security-algorithms</module>
<module>core-java-serialization</module>
<module>core-java-sockets</module>
<module>core-java-streams</module>
<module>core-java-streams-simple</module>
<module>core-java-streams-3</module>
Expand Down