`
0428loveyu
  • 浏览: 30784 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

用Java编写一个服务器

 
阅读更多

一个简单的服务器实现,采用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);
	}

	@Override
	public 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();
		}
	}

	@Override
	public 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")) { // GET
					File requestedFile = getFileFromRequest(stringTokenizer);
					version = getVersionFromRequest(stringTokenizer);
					if (accessiable(requestedFile)) {// OK
						processSucess(raw, requestedFile, version);
					} else { // not file found
						processFailure(out, ResponseState.FNF, version);
					}
				} else { // not GET
					processFailure(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;
	}

}


分享到:
评论

相关推荐

    java编写的游戏服务器.zip

    java编写的游戏服务器java编写的游戏服务器 java编写的游戏服务器java编写的游戏服务器 java编写的游戏服务器java编写的游戏服务器 java编写的游戏服务器java编写的游戏服务器 java编写的游戏服务器java编写的游戏...

    JAVA编写客户端向服务器传输文件

    总结起来,使用Java编写客户端向服务器传输文件涉及到的主要知识点有:Java的Socket和ServerSocket类,网络通信的基本原理,文件的输入/输出流操作,以及可能涉及的多线程、异常处理和安全性策略。理解这些概念并能...

    java编写的浏览器和服务器

    本项目涉及的是使用Java编写的一个简单的浏览器和服务器,这对于学习Java网络编程的初学者来说是一个很好的实践案例。 首先,我们要理解浏览器和服务器的基本工作原理。浏览器是客户端应用程序,用于向服务器发送...

    用java编写的web服务器

    下面,我们将深入探讨如何使用Java创建一个基本的Web服务器,并理解其背后的原理。 ### 1. Java Web服务器的基本结构 在提供的`WebServer.java`代码中,我们首先看到了对Java标准库中`java.io`和`java.net`包的...

    用java编写的一个服务器

    在Java编程领域,创建一个服务器是一项基础且重要的任务,它涉及到网络编程和多线程的知识。这个特定的项目包括两个核心文件:`WebThread.java` 和 `WebServlet.java`,它们共同构成了一个简单的服务器框架。 首先...

    java编写的简易HTTP服务器

    java编写的简易HTTP服务器

    使用Java编写的一个简易多线程HTTP服务器

    标题中的“使用Java编写的一个简易多线程HTTP服务器”指的是一个使用Java编程语言实现的简单HTTP服务器,它利用了多线程技术来处理客户端的HTTP请求。在Java中,可以使用Socket编程接口来建立TCP连接,进而实现HTTP...

    通过java编写客户端,服务器程序,实现聊天功能

    当有客户端连接时,`accept()`方法会返回一个新的Socket对象,我们可以用它来获取输入流和输出流,进而读取和发送数据。 客户端则需要创建一个Socket对象,指定服务器的IP地址和端口号,然后同样获取输入流和输出流...

    Java 游戏服务器 仿照网狐内核编写.zip

    Java 游戏服务器 仿照网狐内核编写.zipJava 游戏服务器 仿照网狐内核编写.zip Java 游戏服务器 仿照网狐内核编写.zipJava 游戏服务器 仿照网狐内核编写.zip Java 游戏服务器 仿照网狐内核编写.zipJava 游戏服务器 ...

    用java编写的简单聊天程序

    【标题】:“用Java编写的简单聊天程序” 在IT领域,Java是一种广泛使用的面向对象的编程语言,以其“一次编写,到处运行”的特性而闻名。本项目是一个基于Java实现的简单聊天程序,它展示了如何利用Java进行网络...

    个人使用JAVA编写的聊天程序

    本项目是个人使用JAVA编写的聊天程序,它实现了基本的即时通讯功能,用户之间可以进行文字聊天并发送表情,具有实时性的特点。 首先,我们要了解Java聊天程序的基础架构。在Java中,通常会采用Socket编程来实现网络...

    java编写的简单DNS服务器代码

    java编写的简单DNS服务器代码,可用于二次开发,或者作为测试

    java编写的代理服务器

    java编写的代理服务器 学习工作的好参考 大家可以参考下

    java编写源代码简易聊天系统

    总的来说,Java编写的简易聊天系统是一个综合运用了网络编程、多线程、输入/输出流、用户界面设计等多个Java核心概念的项目。通过这个系统,开发者可以深入理解Java在网络应用中的实际运用,同时也能提升处理并发和...

    一个java编写的程序

    这个名为"网络下载管理器"的程序,可能是用Java编写的一个工具,用于帮助用户更有效地管理和控制他们的网络下载。下载管理器通常具备以下功能: 1. **多任务下载**:允许用户同时下载多个文件,提高了下载效率。 2....

Global site tag (gtag.js) - Google Analytics