Il programma HTTPServer definisce il funzionamento di base di un Server Web multithreading che implementa il protocollo HTTP 1.1 . Il server :
In pratica il Browser effettua la richiesta:
Cache-Control : no-cache Cache-Control : private // Expire : 0 HTTPServer.java:
import java.net.*;
public class HTTPServer {
/* MAIN */
// Crea un istanza di HTTPServer e richiama il metodo Run della stessa if(args.length > 0) server.processCommandLine(args); server.run(); public HTTPServer() {
// Valutazione dei parametri passati nella linea di comando public void processCommandLine(String[] args) { break; String logFile = config.getLogFile(); if(logFile!="") logger = new Logger(logFile,config.echoToConsole());
/* Visualizzazione versione del Server */ public void displayVersionInfo() {
public void run() { config.display(); // Caratteristiche del Server try { ServerSocket server = new ServerSocket(config.getServerPort()); int localPort = server.getLocalPort(); logger.datedLog(NAME+" is listening on port "+localPort+"."); do { Socket client = server.accept(); // Ricevuta la richiesta si apre per il servizio un nuovo ServerThread che estende la classe Thread (new HTTPServerThread(client,config,logger)).start(); System.exit(0); }
/********************************************************************
Ogni volta che un cliente si connette, si apre un Thread nuovo e al quale si affida la gestione della connessione.
********************************************************************/
class HTTPServerThread extends Thread { public HTTPServerThread(Socket client,ServerConfiguration config, Logger logger) { this.config = config; this.logger = logger;
// Corpo del Thread public void run() { describeConnection(client); // Si creano oggetti delle classi HTTPOutputStream e HTTPInputStream per comunicare col Client. I flussi sono memorizzati in buffer per mogliorare le prestazioni di I/O HTTPOutputStream outStream = new HTTPOutputStream( new BufferedOutputStream(client.getOutputStream())); HTTPInputStream inStream = new HTTPInputStream(client.getInputStream()); // Cattura le richieste HTTP di input HTTPRequest request = inStream.getRequest(); request.log(logger); if(request.isGetRequest()) { String ext = request.getExtName(config); // Se il file trasmesso è un archivio ".jar", comunica al Browser di non trattenerlo poiché nella Cache ha validità per 0 sec. if (ext.equals("jar")) response +="Expire : 0 \n"; outStream.println(response); outStream.println(); logger.datedLog("Send msg: "+ response); processGetRequest(request,outStream); logger.datedLog("Request completed. Closing connection."); try { logger.datedLog("Connection with client closed."); void describeConnection(Socket client) { String destAddr = client.getInetAddress().getHostAddress(); int destPort = client.getPort(); logger.datedLog("Accepted connection to "+destName+" (" +destAddr+")"+" on port "+destPort+"."); void processGetRequest(HTTPRequest request,HTTPOutputStream outStream) throws IOException { String Registrato = "C:\\Inetpub\\WwwRoot\\Registrato.html"; String fileName = request.getFileName(config);
/* Attraverso HTTPServer possono essere richiesti solo i file :
if((fileName.equals(Registrati)) || (fileName.equals(Registrato)) ) { fileName="C:\\Inetpub\\WwwRoot\\Default.html"; File file = new File(fileName); if(file.exists()) { if(inServerRoot(fullPath)) { sendFile(outStream,file); public boolean inServerRoot(String fileName) { int fileLength = fileName.length(); int rootLength = serverRoot.length(); if(fileLength < rootLength) return false; if(serverRoot.equals(fileName.substring(0,rootLength))) return true; return false; void sendFile(HTTPOutputStream out,File file) { int len = (int) file.length(); byte buffer[] = new byte[len]; in.readFully(buffer); in.close(); for(int i=0;i < len;++i) out.write(buffer[i]); out.flush(); out.close(); logger.datedLog("File sent: "+file.getCanonicalPath()); logger.log("Number of bytes: "+len);
}
class HTTPInputStream extends FilterInputStream { public String readLine() throws IOException { boolean finished = false; boolean cr = false; do { ch = read(); if(ch==-1) return result.toString(); result.append((char) ch); if(cr && ch==10){ return result.toString(); if(ch==13) cr = true; else cr=false; return result.toString(); public HTTPRequest getRequest() throws IOException { String line; do { if(line.length() > 0) request.addLine(line); else break; return request;
}
class HTTPOutputStream extends FilterOutputStream { public void println() throws IOException { write(10); public void println(String s) throws IOException { println(); }
class HTTPRequest { public void addLine(String line) { boolean isGetRequest() { if(firstLine.length() > 0) return false; String getFileName(ServerConfiguration config) { String fileName = firstLine.substring(firstLine.indexOf(" ")+1); int n = fileName.indexOf(" "); if(n!=-1) fileName = fileName.substring(0,n); try { if(fileName.equals("")) fileName = config.getDefaultFile(); if(fileName.charAt(fileName.length()-1)=='/') String getExtName(ServerConfiguration config) { String extName = firstLine.substring(firstLine.indexOf(" ")+1); int n = extName.indexOf(" "); if(n!=-1) extName = extName.substring(0,n); try { if(extName.equals("")) extName = config.getDefaultFile(); if(extName.charAt(extName.length()-1)=='/') extName = extName.substring(n,extName.length()); return extName; String prepareResponse() { for (int i=0;i < lines.size();++i) { int n = line.indexOf("1"); line=line.substring(n,line.length()); lineOut+=line; // Ritorna lo Stato del Server lineOut+=" 200 \n"; // Ritorna di altri eventuali parametri lineOut+="Cache-Control : no-cache \n"; lineOut+="Cache-Control : private \n"; // lineOut+="Expire : 0 \n"; Nel caso si decida di non permettere la memorizzazione in Cache di ogni file che il Server trasmette return lineOut; void log (Logger logger) { for(int i=0;i < lines.size();++i) } // Questa classe si occupa della configurazione del Server Web
class ServerConfiguration {
public ServerConfiguration() { public char getCommentChar() { public int getServerPort() { public String getServerRoot() { public String getDefaultFile() { public String getLogFile() { public boolean echoToConsole() { public void display() { System.out.println(" serverRoot: "+serverRoot); System.out.println(" defaultFile: "+defaultFile); System.out.println(" logFile: "+logFile); System.out.println(" echoLogToConsole: "+echoLogToConsole); public void processConfigurationFile(String fname) { if(file.exists()) { String line; while((line=reader.readLine())!=null) public void processConfigurationLine(String line) throws NumberFormatException { if(line.length()==0) return; int n; int n1 = line.indexOf(' '); int n2 = line.indexOf('\t'); if(n1 == -1) n = n2; else if(n2 == -1) n = n1; else if(n1 < n2) n = n1; else n = n2; if(n==-1 || n==line.length()-1) return; String param = line.substring(0,n); String value = line.substring(n+1); if(param.equals("serverPort")) if(!serverRoot.equals("")){ if(ch!='/' && ch!='\\') serverRoot+="/"; String removeLeadingWhiteSpace(String line) { do { char ch = line.charAt(0); if(ch==CONFIG_COMMENT_CHAR) return ""; if(ch!=' ' && ch!='\t') return line; line=line.substring(1); return ""; } // Esempio di file di configurazione: config.txt // Questa classe si occupa della registrazione delle operazioni effettuate. // La registrazione può essere effettuata su console o su file. class Logger { public boolean echoLogToConsole = true; public BufferedWriter writer = null;
public Logger() { public Logger(String fname, boolean echo) { echoLogToConsole = echo; try { void logMsg(String msg) { writer.newLine(); writer.flush(); if(echoLogToConsole) System.out.println(msg); public synchronized void log(String msg) { public synchronized void datedLog(String msg) {
|