Skip to content

Instantly share code, notes, and snippets.

@mike-neck
Created May 25, 2013 13:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mike-neck/5649095 to your computer and use it in GitHub Desktop.
Save mike-neck/5649095 to your computer and use it in GitHub Desktop.
package org.mikeneck.multithreads;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author mike
*/
public class AddressUtility {
private final InetAddress address;
public AddressUtility(InetSocketAddress socketAddress) {
this(socketAddress.getAddress());
}
public AddressUtility(InetAddress address) {
this.address = address;
}
public void connectionLog() {
System.out.println("connection from [" + asString() + "].");
}
public void messageLog (String message) {
System.out.println("message from [" + asString() + "] : " + message);
}
public String asString () {
StringBuilder builder = new StringBuilder();
for (Iterator<Integer> iterator = asIntegerList().iterator();
iterator.hasNext();) {
int value = iterator.next();
builder.append(value < 0 ? 256 + value : value);
if (iterator.hasNext())
builder.append('.');
}
return builder.toString();
}
private List<Integer> asIntegerList () {
byte[] bytes = address.getAddress();
List<Integer> integers = new ArrayList<>(bytes.length);
for (byte b : bytes) {
integers.add((int) b);
}
return integers;
}
}
package org.mikeneck.multithreads;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* @author mike
*/
public class SimpleClient implements AutoCloseable {
private final Socket socket;
private DataOutputStream output;
private BufferedReader input;
public SimpleClient(String hostname, int port) throws IOException {
socket = new Socket(hostname, port);
}
public SimpleClient open () throws IOException {
output = new DataOutputStream(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
return this;
}
public String sendMessage(String message) throws IOException {
output.writeBytes(message + '\n');
String line;
if ((line = input.readLine()) != null) {
return line;
} else {
return "";
}
}
public void bye () throws IOException {
output.writeBytes("BYE\n");
}
@Override
public void close() throws Exception {
if (!socket.isClosed()) {
socket.close();
}
}
}
package org.mikeneck.multithreads;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author mike
*/
public class SimpleServer implements Runnable {
private final ServerSocket serverSocket;
private boolean quietMode = false;
public SimpleServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public SimpleServer withQuietMode () {
this.quietMode = true;
return this;
}
@Override
public void run() {
while(true) {
try (Socket socket = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream writer = new PrintStream(socket.getOutputStream())
) {
if (!quietMode)
new AddressUtility((InetSocketAddress) socket.getRemoteSocketAddress())
.connectionLog();
String line = reader.readLine();
if (!quietMode)
new AddressUtility((InetSocketAddress) socket.getRemoteSocketAddress())
.messageLog(line);
writer.println(line);
if (line.equals("BYE")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package org.mikeneck.multithreads;
import org.junit.*;
import org.junit.experimental.runners.Enclosed;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
/**
* @author mike
*/
@RunWith(Enclosed.class)
public class SimpleSocketTest {
public static class SingleClient {
private static final ExecutorService SERVICE = Executors.newFixedThreadPool(1);
private static final int PORT = 12521;
private static final String LOCALHOST = "localhost";
private SimpleClient client;
@Rule
public TestName testName = new TestName();
@BeforeClass
public static void start () throws IOException {
SERVICE.execute(new SimpleServer(PORT));
}
@Before
public void setup () throws IOException {
client = new SimpleClient(LOCALHOST, PORT);
}
@After
public void tearDown () throws Exception {
System.out.println(testName.getMethodName() + " is closing");
client.close();
}
@AfterClass
public static void end () throws IOException {
new SimpleClient(LOCALHOST, PORT).open().bye();
}
@Test
public void socketProcessing () throws IOException {
client.open();
String message = client.sendMessage("Hello");
System.out.println("Message from Server [" + message + "]");
assertThat(message, is("Hello"));
System.out.println("Assertion ends.");
}
}
public static class SendManyMessages {
private static final ExecutorService SERVICE = Executors.newFixedThreadPool(1);
private static final int PORT = 14541;
private static final String LOCALHOST = "localhost";
@Rule
public TestName testName = new TestName();
@BeforeClass
public static void start () throws IOException {
SERVICE.execute(new SimpleServer(PORT));
}
@AfterClass
public static void end () throws IOException {
new SimpleClient(LOCALHOST, PORT).open().bye();
}
@ThisTestWillFail
@Test
public void send2times () throws IOException {
SimpleClient client = new SimpleClient(LOCALHOST, PORT).open();
assertThat(client.sendMessage("hello"), is("hello"));
assertThat(client.sendMessage("good-bye"), is("good-bye"));
}
}
public static class ManyThreadClient {
private static final ExecutorService SERVICE = Executors.newFixedThreadPool(1);
private static final int PORT = 11511;
private static final String LOCALHOST = "localhost";
@Rule
public TestName testName = new TestName();
@BeforeClass
public static void start () throws IOException {
SERVICE.execute(new SimpleServer(PORT).withQuietMode());
}
@AfterClass
public static void end () throws IOException {
new SimpleClient(LOCALHOST, PORT).open().bye();
}
@Test
public void testTwoClient () throws IOException, ExecutionException, InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(2);
List<ExpectsAndResult> list = Arrays.asList(
new ExpectsAndResult("1st", LOCALHOST, PORT),
new ExpectsAndResult("2nd", LOCALHOST, PORT)
);
for (ExpectsAndResult item : list) {
item.setFuture(service.submit(item.createClient()));
}
for (ExpectsAndResult item : list) {
assertThat(item.real().endsWith(item.expect()), is(true));
}
}
@Test
public void testManyAccessWith4Pool () throws IOException, ExecutionException, InterruptedException {
int size = 600;
ExecutorService service = Executors.newFixedThreadPool(4);
List<ExpectsAndResult> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(new ExpectsAndResult("message-" + i, LOCALHOST, PORT));
}
for (ExpectsAndResult item : list) {
item.setFuture(service.submit(item.createClient()));
}
for (ExpectsAndResult item : list) {
assertThat(item.real().endsWith(item.expect()), is(true));
}
}
}
static class ExpectsAndResult {
final String message;
final String hostname;
final int port;
Future<String> future;
ExpectsAndResult(String message, String hostname, int port) {
this.message = message;
this.hostname = hostname;
this.port = port;
}
String expect() {
return message;
}
Client createClient () throws IOException {
return new Client(message, hostname, port);
}
void setFuture(Future<String> future) {
this.future = future;
}
String real () throws ExecutionException, InterruptedException {
return future.get();
}
}
static class Client implements Callable<String> {
private final String message;
private final SimpleClient client;
Client(String message, String hostname, int port) throws IOException {
this.message = message;
client = new SimpleClient(hostname, port);
}
@Override
public String call() throws Exception {
client.open();
String name = Thread.currentThread().getName();
return client.sendMessage("Thread [" + name + "] - " + message);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment