用Java编写一个服务器

来源:互联网 发布:iphone手机测评软件 编辑:程序博客网 时间:2024/05/22 01:54

一个简单的服务器实现,采用Java语言。

/** *  */package iotest.serversocket;import java.io.File;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;/** * @author Brandon B. Lin *  */public class JHTTP extends Thread {private File documentRootDirectory;private String indexFileName = "index.html";private ServerSocket server;private int threadCount = 50;public JHTTP(File documentRootDirectory, int port, String indexFileName)throws IOException {if (!documentRootDirectory.isDirectory()) {throw new IOException(documentRootDirectory+ " does not exist as a directory");}this.documentRootDirectory = documentRootDirectory;this.indexFileName = indexFileName;this.server = new ServerSocket(port);}public JHTTP(File documentRootDirectory, int port) throws IOException {this(documentRootDirectory, port, "index.html");}public JHTTP(File documentRootDirectory) throws IOException {this(documentRootDirectory, 80);}@Overridepublic void run() {createThreadPools();logServerInfo(server);acceptConnection();}private void createThreadPools() {for (int i = 0; i < threadCount; i++) {Thread t = new Thread(new RequestProcessor(documentRootDirectory,indexFileName));t.start();}}private void logServerInfo(ServerSocket server) {System.out.println("Accepting connections on port "+ server.getLocalPort());System.out.println("Document Root: " + documentRootDirectory);}private void acceptConnection() {while (true) {try {Socket request = server.accept();RequestProcessor.processRequest(request);} catch (IOException exception) {}}}public static void main(String[] args) {File root = new File("F:\\Java\\document\\docs");int port = 80;startServer(root, port);}private static void startServer(File rootDirectory, int port) {try {JHTTP webServer = new JHTTP(rootDirectory, port);webServer.start();} catch (IOException e) {System.out.println("Server could not start because of an "+ e.getClass());e.printStackTrace();}}}

/** *  */package iotest.serversocket;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.Reader;import java.io.Writer;import java.net.Socket;import java.util.Date;import java.util.LinkedList;import java.util.List;import java.util.StringTokenizer;/** * @author Brandon B. Lin *  */public class RequestProcessor implements Runnable {private static List<Socket> socketPool = new LinkedList<>();private File documentRootDirectory;private String indexFileName = "index.html";public RequestProcessor(File documentRootDirectory, String inexFileName) {if (documentRootDirectory.isFile()) {throw new IllegalArgumentException("DocumentRootDirectory must be a directory, not a file");}this.documentRootDirectory = documentRootDirectory;try {this.documentRootDirectory = documentRootDirectory.getCanonicalFile();} catch (IOException exception) {exception.printStackTrace();}if (inexFileName != null)this.indexFileName = inexFileName;}public static void processRequest(Socket request) {synchronized (socketPool) {socketPool.add(socketPool.size(), request);socketPool.notifyAll();}}@Overridepublic void run() {while (true) {String version = "";try (Socket connection = getRequestFromJobQueue()) {Reader in = new InputStreamReader(new BufferedInputStream(connection.getInputStream()), "ASCII");String request = readRequest(in);System.out.println(request);OutputStream raw = new BufferedOutputStream(connection.getOutputStream());Writer out = new OutputStreamWriter(raw);StringTokenizer stringTokenizer = new StringTokenizer(request);String method = stringTokenizer.nextToken();if (method.equals("GET")) { // GETFile requestedFile = getFileFromRequest(stringTokenizer);version = getVersionFromRequest(stringTokenizer);if (accessiable(requestedFile)) {// OKprocessSucess(raw, requestedFile, version);} else { // not file foundprocessFailure(out, ResponseState.FNF, version);}} else { // not GETprocessFailure(out, ResponseState.NIP, version);}} catch (IOException exception) {exception.printStackTrace();}}}private Socket getRequestFromJobQueue() {synchronized (socketPool) {while (socketPool.isEmpty()) {try {socketPool.wait();} catch (InterruptedException exception) {}}return socketPool.remove(0);}}private String readRequest(Reader in) throws IOException {StringBuffer requestLine = new StringBuffer();int readByte;while (true) {readByte = in.read();if (readByte == '\r' || readByte == '\n')break;requestLine.append((char) readByte);}return requestLine.toString();}private byte[] readRequestedFile(File requestedFile) throws IOException {DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(requestedFile)));byte[] theData = new byte[(int) requestedFile.length()];fis.readFully(theData);fis.close();return theData;}private File getFileFromRequest(StringTokenizer stringTokenizer) {String fileName = stringTokenizer.nextToken();if (fileName.endsWith("/")) {fileName += indexFileName;}File theFile = new File(documentRootDirectory, fileName.substring(1,fileName.length()));return theFile;}private String getVersionFromRequest(StringTokenizer stringTokenizer) {String version = "";if (stringTokenizer.hasMoreTokens()) {version = stringTokenizer.nextToken();}return version;}private void processSucess(OutputStream raw, File requestedFile,String version) throws IOException {byte[] theData = readRequestedFile(requestedFile);String contentType = guessContentTypeFromRequest(requestedFile.getName());if (version.startsWith("HTTP")) {writeHeader(new OutputStreamWriter(raw), ResponseState.OK,new Content(contentType, theData.length));}raw.write(theData);raw.flush();}private boolean accessiable(File requestedFile) throws IOException {return requestedFile.canRead()&& requestedFile.getCanonicalPath().startsWith(documentRootDirectory.getPath());}private void processFailure(Writer out, ResponseState state, String version)throws IOException {if (version.startsWith("HTTP ")) {writeHeader(out, state, new Content("text/html", -1));}writeHint(out, state);}private void writeHeader(Writer out, ResponseState state, Content content)throws IOException {out.write("HTTP/1.0" + state.getStateCode() + state.getHint() + "\r\n");Date now = new Date();out.write("Data: " + now + "\r\n");out.write("Server: JHTTP/1.0 \r\n");if (content.getContenLength() != -1) {out.write("Content-length: " + content.getContenLength() + "\r\n");}out.write("Content-Type: " + content.getContentType() + "\r\n\r\n");out.flush();}private void writeHint(Writer out, ResponseState state) throws IOException {out.write("<HTML>\r\n");out.write("<HEAD><TITLE>" + state.getHint() + "</TITLE>\r\n");out.write("</HEAD>\r\n");out.write("<BODY>");out.write("<H1>HTTP Error " + state.getStateCode() + ": "+ state.getHint() + "</H1>\r\n");out.write("</BODY></HTML>\r\n");out.flush();}public static String guessContentTypeFromRequest(String request) {String exetension = getExtension(request);switch (exetension) {case "html":case "htm":return "text/html";case "txt":case "java":return "text/plain";case "gif":return "image/gif";case "class":return "application/octet-stream";case "jpg":case "jpeg":return "image/jpeg";default:return "text/plain";}}public static String getExtension(String fileName) {return fileName.substring(fileName.lastIndexOf('.')+1, fileName.length());}class Content {private String contentType;private int contenLength;public Content(String contentType, int contentLength) {this.contentType = contentType;this.contenLength = contentLength;}public String getContentType() {return contentType;}public void setContentType(String contentType) {this.contentType = contentType;}public int getContenLength() {return contenLength;}public void setContenLength(int contenLength) {this.contenLength = contenLength;}}}

/** *  */package iotest.serversocket;/** * @author Brandon B. Lin *  */public enum ResponseState {OK(200, "OK"), FNF(404, "File Not Found"), NIP(501, "Not Implemented");private int stateCode;private String hint;ResponseState(int stateCode, String hint) {this.stateCode = stateCode;this.hint = hint;}public int getStateCode() {return stateCode;}public void setStateCode(int stateCode) {this.stateCode = stateCode;}public String getHint() {return hint;}public void setHint(String hint) {this.hint = hint;}}


0 0