Beispiel: Einfacher HTTP-Server

Dieser Server schickt nur die gefragte Datei zurück. Die Klasse selbst ist ein Thread, der in der main() für jede Verbindung neu gestartet wird. Dies ist effizienter, als jedesmal einen Kind-Prozeß zu erzeugen.
 
import java.net.Socket;
import java.net.ServerSocket;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.PrintStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.StringTokenizer;
import sun.servlet.http.HttpDate;

public class BasicHttp extends Thread

 Socket Connect;   // Die Socket der Verbindung
 static String Docroot;  // Root des Server-Dateisystems
 static String Indexfile;
 
 public static void main(String args[])
 { // Die Parameter sind Docroot (ohne letzten '/'), Indexfile, Port
  int port;   // Der Port, an dem der Server warten soll
  ServerSocket socket;// Die Socket des Servers
  Socket connection; // Die Socket der Verbindung
 
  System.out.println( "Starte ..." );
// Versuch, Root und Name des Indexfiles aus den Parametern zu lesen:
  try
  { Docroot = args[0]; }
  catch (Exception e)
  { Docroot = "."; }
  try
  { Indexfile = args[1]; }
  catch (Exception e)
  { Indexfile = "index.html"; }
// Versuch, den Port aus den Parametern zu lesen:
  try
  {
   port = Integer.parseInt(args[2]);
   if (port < 0 || port > 65535) port = 0;
  }
  catch (Exception e)
  { port = 0; }
  try
  {
   socket = new ServerSocket(port);
    // Erzeugen einer Socket
   System.out.println("Warte auf Verbindung an Port "
    + socket.getLocalPort());
   System.out.println("Docroot: " + Docroot);
   System.out.println("Indexfile: " + Indexfile);
   while (true)
   { // Endlos auf Verbindungen warten ...
    while (activeCount() > 100);
     // max. 100 Threads starten, geg. warten
    new BasicHttp(socket.accept()).start();
     // fuer jede Verbindung ein neuer Thread
   }
  }
  catch (Exception e)
  { // Ganz gleich welcher Fehler ...
    System.err.println("Ouch!!!");
  }
 }
 
// Konstruktor
 public BasicHttp(Socket s)
 {
  Connect = s;
 }

// Verarbeiten der Requests
 public void run()
 {
  try
  {
   PrintStream os = new PrintStream(Connect.getOutputStream());
   BufferedReader br = new BufferedReader(
    new InputStreamReader(Connect.getInputStream()));
// erste Zeile lesen; z.B. "GET /hallo.html HTTP/1.0"
   String get = br.readLine();
   StringTokenizer st = new StringTokenizer(get);
   String method = st.nextToken();  // Methode
   String filename = st.nextToken(); // Request-URI
   if (filename.endsWith("/")) // evt. Indexfile anhaengen
    filename += Indexfile;
   String ct = guessContentType(filename); // Content-Type
   String version = "";
   if (st.hasMoreTokens())
    version = st.nextToken();
// restliche Sendung ignorieren
   Connect.getInputStream().skip(Connect.getInputStream().available());
   try
   {
// die gefragte Datei lesen
    filename = Docroot + filename;
    File file = new File(filename);
    FileInputStream fis = new FileInputStream(filename);
    byte[] data = new byte[(int)file.length()];
    fis.read(data);
    fis.close();
// geg. Status-Zeile und Header senden
    if (version.startsWith("HTTP/1"))
    {
     os.print("HTTP/1.0 200 OK\r\n");
     os.print("Date: " +
      new HttpDate(HttpDate.getCurrentTime()) + "\r\n");
     os.print("Server: BasicHttp/1.2\r\n");
     os.print("Content-length: " + file.length() + "\r\n");
     os.print("Content-type: " + ct + "\r\n\r\n");
    }
// geg. Datei senden
    if (! method.equals("HEAD"))
     os.write(data);
    Connect.close();
   }
   catch (IOException e)
   {
// geg. File Not Found-Meldung senden
// geg. Status-Zeile und Header senden
    if (version.startsWith("HTTP/1"))
    {
     os.print("HTTP/1.0 404 File Not Found\r\n");
     os.print("Date: " +
      new HttpDate(HttpDate.getCurrentTime()) + "\r\n");
     os.print("Server: BasicHttp/1.2\r\n");
     os.print("Content-type: text/html\r\n\r\n");
    }
    os.print("<HTML><HEAD><TITLE>File Not Found</TITLE></HEAD>"
     + "<BODY><H1>HTTP Error 404: File Not Found</H1></BODY></HTML>");
    Connect.close();
    System.err.println("Datei nicht gefunden: " + filename);
   }
  }
  catch (IOException e)
  {
   System.err.println("Unbekannter Fehler: " + e);
  }
  System.out.println("Anfrage um " + new HttpDate(
    HttpDate.getCurrentTime()));

 }
 
 public String guessContentType(String name)
 { // erraet den MIME-Type anhand der Extension
  if (name.endsWith(".html") || name.endsWith(".htm"))
    return "text/html";
  else if (name.endsWith(".txt") || name.endsWith(".java"))
    return "text/plain";
  else if (name.endsWith(".gif")) return "image/gif";
  else if (name.endsWith(".class"))
    return "application/octet-stream";
  else if (name.endsWith(".jpg") || name.endsWith(".jpeg"))
    return "image/jpeg";
  else return "text/plain";
 }

}

class HttpDate
{ // Wer java.text.DateFormat verstanden hat, kann das gerne umschreiben.
 protected static String Days[] = {"Sat", "Sun", "Mon", "Tue",
    "Wed", "Thu", "Fri"};
 protected static String Months[] = {"Jan" , "Feb" , "Mar" ,
    "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 
 public static String Format(java.util.Calendar date)
 {
  return new String(Days[date.get(Calendar.DAY_OF_WEEK)]  + ", "
    + date.get(Calendar.DAY_OF_MONTH) + " "
    + Months[date.get(Calendar.MONTH)] +  " "
    + date.get(Calendar.YEAR) + " " + date.get(Calendar.HOUR_OF_DAY)
    + ":" + date.get(Calendar.MINUTE) + ":"
    + date.get(Calendar.SECOND) + " GMT");
 }
 
 public static String Now()
 {
  return Format(Calendar.getInstance(java.util.TimeZone.getTimeZone("GMT")));
 }

}