基于socket阻塞模式的 java 简单服务器

没怎么关注socket这地块..多半是知其然,不知其所以然

闲着无聊..写了一个简单的java服务器,供新人复习.

把类贴到jee工程中 将静态文件放至wwwroot目录 运行main函数即可访问

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * 基于阻塞 模式的简单的java服务器
 * 
 * @author 衣旧 2010-06-06
 */
public class HttpServer {

	/**
	 * 监听本地端口
	 */
	private ServerSocket serverSocket;

	/**
	 * 根目录
	 */
	public static final String WEB_ROOT = System.getProperty("user.dir")+ File.separator + "wwwroot";
	/**
	 * 服务器监听端口, 默认为 80.
	 */
	public static int PORT = 80;

	/**
	 * 开始服务器 Socket 线程.
	 */
	public HttpServer() {
		try {
			serverSocket = new ServerSocket(PORT);
			while (true) {
				Socket client = serverSocket.accept();
				new IoHandler(client);
			}
		} catch (Exception e) {
			System.out.println("无法启动HTTP服务器:" + e.toString());
		}
		if (serverSocket == null)
			System.exit(1);// 无法开始服务器
		System.out.println("HTTP 服务器正在运行,端口:" + PORT);
	}

	/**
	 * 打印用途说明.
	 */
	private static void usage() {
		System.out
				.println("Usage: java serverSocket <port>\nDefault port is 80.");
	}

	/**
	 * 启动简易 HTTP 服务器
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			if (args.length != 1) {
				usage();
			} else if (args.length == 1) {
				PORT = Integer.parseInt(args[0]);
			}
		} catch (Exception ex) {
			System.err.println("初始端口. 必须是大于0的整数!\n" + ex.toString());
		}
		new HttpServer();
	}

	/**
	 * 响应http请求
	 * 
	 * @author liucf
	 * 
	 */
	class IoService {

		private IoProcessor request;
		private PrintWriter out;
		private PrintStream outs;
		private int BUFFER_SIZE = 1024;

		IoService(PrintWriter output, PrintStream outs) {
			this.out = output;
			this.outs = outs;
		}

		public IoProcessor getRequest() {
			return request;
		}

		public void setRequest(IoProcessor request) {
			this.request = request;
		}

		public void responseInfo() {
			if ("POST".equalsIgnoreCase(request.getMethod())
					&& request.getContentLength() > 0) {
//				System.out.println("以下内容为 POST 方式提交的表单数据");
//				for (int i = 0; i < request.getContentLength(); i++) {
//					try {
//						System.out.print((char) request.getIn().read());
//					} catch (IOException e) {
//						e.printStackTrace();
//					}
//				}
			}

			if ("GET".equalsIgnoreCase(request.getMethod())) {
				doGet();
			}
		}

		public void doGet() {
			File file = new File(HttpServer.WEB_ROOT, request.getUri());
			if (file.isDirectory()) {
				out.println("HTTP/1.0 200 OK");// 返回应答消息,并结束应答
				out.println("Content-Type:text/html;charset=GBK");
				out.println();
				out.println("<h1>不允许访问文件夹!!</h1>");
			} else if (file.exists()) {
				byte[] bytes = new byte[BUFFER_SIZE];
				FileInputStream fis = null;
				if (file.exists()) {
					try {
						fis = new FileInputStream(file);
						int ch = fis.read(bytes, 0, BUFFER_SIZE);
						while (ch != -1) {
							outs.write(bytes, 0, ch);
							ch = fis.read(bytes, 0, BUFFER_SIZE);
						}
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			} else {
				out.println("HTTP/1.0 404 Not found");// 返回应答消息,并结束应答
				out.println("Content-Type:text/html;charset=GBK");
				out.println();
				out.println("<h1>访问路径不存在!!</h1>");
			}
		}
	}

	/**
	 * 
	 * 封装处理http请求信息
	 * 
	 * @author liucf
	 * 
	 */
	class IoProcessor {
		private BufferedReader in;
		private String uri;
		private String method;
		private int contentLength;
		private Map<String, Object> http = new HashMap<String, Object>();

		public IoProcessor(BufferedReader in) {
			this.in = in;
			parseRequstInfo();
		}

		private void parseRequstInfo() {
			String line = null;
			try {
				line = in.readLine();
				// 读取第一行, 请求地址
				System.out.println(line);
				String resource = line.substring(line.indexOf('/'), line
						.lastIndexOf('/') - 5);
				// 获得请求的资源的地址
				uri = URLDecoder.decode(resource, "UTF-8");// 反编码
				// 地址
				method = new StringTokenizer(line).nextElement().toString();// 获取请求方法,

				// 读取所有浏览器发送过来的请求参数头部信息
				while ((line = in.readLine()) != null) {
					if (line.equals(""))
						break;
					if (line.indexOf(":") != -1) {
						String key = line.substring(0, line.indexOf(':'))
								.trim();
						String value = line.substring(line.indexOf(':') + 1)
								.trim();
						http.put(key, value);
						// 读取 POST 等数据的内容长度
						if (line.startsWith("Content-Length")) {
							try {
								contentLength = Integer.parseInt(line
										.substring(line.indexOf(':') + 1)
										.trim());
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}
				}
			} catch (IOException e) {
				System.out.println("解析请求出错!");
				e.printStackTrace();
			}
		}

		public BufferedReader getIn() {
			return in;
		}

		public void setIn(BufferedReader in) {
			this.in = in;
		}

		public String getUri() {
			return uri;
		}

		public void setUri(String uri) {
			this.uri = uri;
		}

		public String getMethod() {
			return method;
		}

		public void setMethod(String method) {
			this.method = method;
		}

		public int getContentLength() {
			return contentLength;
		}

		public void setContentLength(int contentLength) {
			this.contentLength = contentLength;
		}

		public Map<String, Object> getHttp() {
			return http;
		}

		public void setHttp(Map<String, Object> http) {
			this.http = http;
		}
	}

	/**
	 * 响应客户端请求
	 * 
	 * @author liucf
	 *
	 */
	class IoHandler implements Runnable {

		private Socket client;// 客户端连接

		private BufferedReader input;// 接收外部信息的流

		private PrintWriter printWriter;// 输出流

		private PrintStream printStream;

		public IoHandler(Socket socket) {
			this.client = socket;
			try {
				input = new BufferedReader(new InputStreamReader(client
						.getInputStream()));
				printWriter = new PrintWriter(new OutputStreamWriter(client
						.getOutputStream(), "GBK"), true);
				printStream = new PrintStream(client.getOutputStream(), true);
			} catch (IOException e) {
				e.printStackTrace();
			}
			this.run();
		}

		public void run() {
			System.out.println("连接到服务器的用户:" + client);
			try {
				IoProcessor request = new IoProcessor(input);
				IoService response = new IoService(printWriter, printStream);
				response.setRequest(request);
				response.responseInfo();
				closeSocket(client);
			} catch (Exception e) {
				System.out.println("HTTP 服务器错误:" + e.toString());
			}
		}

		/**
		 * 关闭客户端 socket 并打印一条调试信息.
		 * 
		 * @param socket
		 *            客户端 socket.
		 */
		public void closeSocket(Socket socket) {
			try {
				printWriter.close();
				socket.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
			System.out.println(socket + "离开了HTTP服务器!\n");
		}
	}
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值