Wednesday, 20 January 2010

A multi-threaded socket-based server

The problem is old - How to implement a multi-threaded, socket-based server that will let you read and write to the client (for example a telnet terminal.There are several problems with constructing such a server:


1.You have to use threads because otherwise clients will be queued up waiting for a connection.

2.Many of the publically available examples (even some in some books) do not work for I/O servers. They are mostly developed around reading from a socket not writing to the socket as well. In our example we give a working read/write code example.

3.You need to avoid race conditions when starting up a thread at times when connections are coming through thick and fast.

The code below will implement just such a server. It is intended for a head start, so is a template rather than a tutorial on how to write a server in Java. We have decided on port 4444 to listen on in the example, but you need to decide on a suitable port yourself.

The server will run, establishing connections from the port and echoing input received until it receives a line of input that is a full stop only ".".

Have fun!

The Kieser.net team.
Honeypot: spam@kieser.net


package sample_server;

import java.io.*;
import java.net.*;
import java.security.*;

/**
* Title: Sample Server
* Description: This utility will accept input from a socket, posting back to the socket before closing the link.
* It is intended as a template for coders to base servers on. Please report bugs to brad at kieser.net
* Copyright: Copyright (c) 2002
* Company: Kieser.net
* @author B. Kieser
* @version 1.0
*/

public class sample_server {

private static int port=4444, maxConnections=0;
// Listen for incoming connections and handle them
public static void main(String[] args) {
int i=0;

try{
ServerSocket listener = new ServerSocket(port);
Socket server;

while((i++ < maxConnections) || (maxConnections == 0)){
doComms connection;

server = listener.accept();
doComms conn_c= new doComms(server);
Thread t = new Thread(conn_c);
t.start();
}
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}

}

class doComms implements Runnable {
private Socket server;
private String line,input;

doComms(Socket server) {
this.server=server;
}

public void run () {

input="";

try {
// Get input from the client
DataInputStream in = new DataInputStream (server.getInputStream());
PrintStream out = new PrintStream(server.getOutputStream());

while((line = in.readLine()) != null && !line.equals(".")) {
input=input + line;
out.println("I got:" + line);
}

// Now write to the client

System.out.println("Overall message is:" + input);
out.println("Overall message is:" + input);

server.close();
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}

4 comments:

  1. This is nice, but some test code would have made it clearer. How does one inject commands like "cd /tmp" and "ls -l" and what happens when you do "vi test.txt"?

    ReplyDelete
  2. You would access the file system as per normal Java programming. However, be aware that you need to be very cautious about allowing access to your file system as that can be a security risk.

    ReplyDelete
  3. You would access the file system as per normal Java programming.

    ReplyDelete
  4. A multi-threaded socket-based server is an exclusive addition to some worthy grinders, I will get to the Jones and see some more information about the Coffee grinder, Hope to enjoy the day well. Thanks for the share.

    ReplyDelete