- There are a couple differences with servers:
    - They have to start running first.
- They need an extra port -- one to listen for clients.
- But once a server has made the connection to the client, it's
really just the same.
- Here is yet more code from David Barnes -- this time I left the
main as he wrote it (in another class) though I really don't see the
advantage... (so no comment claiming I'm a coauthor!)
 
- The server class
 import java.net.*;
 import java.io.*;
 
 // A simple server that accepts a client connection
 // and sends back the length of the strings it
 // receives from the client.
 class LineLengthServer {
 public LineLengthServer(int port) throws Exception {
 try{
 // Listen on the given port.
 serverSocket = new ServerSocket(port);
 }
 catch(BindException e){
 throw new Exception("Failed to create a server socket: "+
 e.getMessage());
 }
 }
 
 // Read strings and return their length (as a String)
 // to the client.
 public void run() throws Exception {
 ServerSocket serverSocket = getServerSocket();
 Socket clientSocket = null;
 try{
 System.out.println("Listening for a client on port: "+
 serverSocket.getLocalPort());
 // Wait for a client to make contact.
 clientSocket = serverSocket.accept();
 // Contact ...
 System.out.println("A client has arrived.");
 
 // Wrap the input stream in a BufferedReader.
 BufferedReader reader = new BufferedReader(
 new InputStreamReader(clientSocket.getInputStream()));
 // Wrap the output stream in a BufferedWriter.
 BufferedWriter writer = new BufferedWriter(
 new OutputStreamWriter(clientSocket.getOutputStream()));
 
 // Read lines until the client terminates.
 String request = reader.readLine();
 while(request != null){
 // Write the length of the line as a String.
 writer.write(String.valueOf(request.length()));
 writer.newLine();
 writer.flush();
 request = reader.readLine();
 }
 }
 catch(IOException e){
 throw new Exception("IOException talking to the client: "+
 e.getMessage());
 }
 finally{
 if(clientSocket != null){
 System.out.println("The client has gone.");
 // Close the socket to the client.
 clientSocket.close();
 }
 }
 serverSocket.close();
 }
 
 protected ServerSocket getServerSocket(){
 return serverSocket;
 }
 
 // The socket on which the listening is done.
 private final ServerSocket serverSocket;
 }
 
 
- The "main" class
         // An example of a simple server that reads lines from
 // clients and sends back the length of each line
 // it receives.
 public class LineLengthServerMain {
 public static void main(String[] args){
 try{
 // An arbitrary port number to listen on. This should be
 // larger than 1024 for user-written servers.
 final int port = 24101;
 LineLengthServer server = new LineLengthServer(port);
 server.run();
 }
 catch(Exception e){
 System.err.println("Exception: "+e.getMessage());
 }
 }
 }
 
 
 
- Running it from linux
 [joanna@sydney Networks]$ javac LineLengthServerMain.java
 [joanna@sydney Networks]$ java LineLengthServer
 Exception in thread "main" java.lang.NoSuchMethodError: main
 [joanna@sydney Networks]$ java LineLengthServerMain
 Listening for a client on port: 24101
 ^Z
 [2]+  Stopped                 java LineLengthServerMain
 [joanna@sydney Networks]$ bg
 [2]+ java LineLengthServerMain &
 [joanna@sydney Networks]$ telnet localhost 24101
 Trying 127.0.0.1...
 A client has arrived.
 Connected to localhost.
 Escape character is '^]'.
 hi there
 8
 have you ever thought
 21
 this isn't really measuring the line length...
 46
 Ah ha!
 6
 ^]
 
 telnet> .
 ?Invalid command
 telnet> quit
 Connection closed.
 The client has gone.
 [2]+  Done                    java LineLengthServerMain
 [joanna@sydney Networks]$
 
    - Notice I used telnet as a client again (see colour
code mentioned earlier).
 
- And also, I suspended the server
process (with ^Z) and then
backgrounded it by typing bg
      - This made it start running
run, but leaving me STDIN to use with telnet.
- You can also type fg and get right back where you
were.
- You could also start the
server in the background in the first place by typing an &
afterwards like this:  j2bryson$
java LineLengthServerMain & 
 
- Note both programs
now shared STDOUT!
 
- Consequently, both programs were printing to the screen at the
same time -- telent I made blue, the server red, and what I typed green.
- I also forgot the telnet
protocol / commands -- I thought you
killed it with a .
      - mail quites with a .
- I got it right the second
guess though.
- Don't be afraid to
hack!
 
- If you want to make a server accept more than one connection,
just put a while loop in so it looks again (see the outlined server
back in section I.)
- If you want to have the server accept new clients while it's
still servicing old ones, you need to use threads!
- Here's an example of that, again from Barnes (hey, he writes good
examples! This is from RandomServiceListener)
     public void listen() throws Exception {
 ServerSocket serverSocket = getServerSocket();
 // Wait up to 30 minutes for new clients.
 final int timeToWait = 1*60*1000;
 boolean keepWaiting = true;
 
 while(keepWaiting){
 try{
 // Wait for a client to make contact.
 serverSocket.setSoTimeout(timeToWait);
 Socket clientSocket = serverSocket.accept();
 // Let a separate Thread handle it.
 new Thread(new RandomService(clientSocket)).start();
 }
 catch(InterruptedIOException e){
 // We timed out waiting for a client.
 keepWaiting = false;
 }
 catch(IOException e){
 throw new Exception("IOException: "+ e.getMessage());
 }
 }
 // No more clients, so close the socket.
 serverSocket.close();
 }
    - Notice not only the threading, but the fact it handles
interupts, so it can eventually be killed!
- It also sets a timeout
so that it will effectively interrupt itself if it's been waiting too
long (as well as accepting terminate signals, e.g. from the keyboard.)