锁定老帖子 主题:用java实现的一个简单的web服务器
精华帖 (0) :: 良好帖 (9) :: 新手帖 (18) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-12-09
最后修改:2009-12-12
/** * 用Java语言实现HTTP服务器,首先启动一个java.net.ServerSocket在提供服务的端口上监听连接.向客户返回文本时,可以用 * PrintWriter,但是如果返回二进制数据,则必须使用OutputStream.write(byte[])方法,返回的应答消息字符串可以使用 * String.getBytes()方法转换为字节数组返回,或者使用PrintStream的print()方法写入文本,用 * write(byte[])方法写入二进制数据. * * 以工程所在目录为web的根目录。 在工程的根目录下放一个大概如下的index.html * * <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" * "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta * http-equiv="Content-Type" content="text/html; charset=gbk"> * <title>简单的测试</title> </head> <body> 你好!这是一个 简单的web服务器。<br> * 这是一个图片!<br> * * <form action="/index.html"> <img alt="" src="images/test.gif"><br> * 姓名:<input type="text" name="name" /><br> * 密码:<input type="password" name="pass"></input><br> * <input type="submit"/> </form> </body> </html> * * 放入图片位置: 工程根目录/images/test.gif <br> * 打开浏览器输入http://localhost/index.html 可以展示index.html * * @author guazi */ public class SimpleHttpServer implements Runnable { ServerSocket serverSocket;// 服务器Socket /** * 服务器监听端口, 默认为 80. */ public static int PORT = 80;// 标准HTTP端口 /** * 开始服务器 Socket 线程. */ public SimpleHttpServer() { try { serverSocket = new ServerSocket(PORT); } catch (Exception e) { System.out.println("无法启动HTTP服务器:" + e.getMessage()); } if (serverSocket == null) System.exit(1);// 无法开始服务器 new Thread(this).start(); System.out.println("HTTP服务器正在运行,端口:" + PORT); } /** * 运行服务器主线程, 监听客户端请求并返回响应. */ public void run() { while (true) { try { Socket client = null;// 客户Socket client = serverSocket.accept();// 客户机(这里是 IE 等浏览器)已经连接到当前服务器 if (client != null) { System.out.println("连接到服务器的用户:" + client); try { // 第一阶段: 打开输入流 BufferedReader in = new BufferedReader( new InputStreamReader(client.getInputStream())); System.out.println("客户端发送的请求信息: ***************"); // 读取第一行, 请求地址 System.out.println("http协议头部信息:"); String line = in.readLine(); System.out.println(line); String resource = line.substring(line.indexOf('/'), line.lastIndexOf('/') - 5); // 获得请求的资源的地址 resource = URLDecoder.decode(resource, "gbk");// 反编码 String method = new StringTokenizer(line).nextElement() .toString();// 获取请求方法, GET 或者 POST // 读取浏览器发送过来的请求参数头部信息 while ((line = in.readLine()) != null) { System.out.println(line); if (line.equals("")) break; } System.out.println("http协议头部结束 ***************"); System.out.println("用户请求的资源是:" + resource); System.out.println("请求的类型是: " + method); String params = null; if (resource.indexOf("?") > -1) { params = resource .substring(resource.indexOf("?") + 1); resource = resource.substring(0, resource .indexOf("?")); } // 显示 POST 表单提交的内容, 这个内容位于请求的主体部分 if ("POST".equalsIgnoreCase(method)) { if (params != null) { params +="&" + in.readLine(); }else{ params =in.readLine(); } } System.out.println("打印提交的数据:"); printParams(params); // 读取资源并返回给客户端 fileReaderAndReturn(resource, client); // 关闭客户端链接 client.close(); System.out.println("客户端返回完成!"); } catch (Exception e) { System.out.println("HTTP服务器错误:" + e.getMessage()); } } } catch (Exception e) { System.out.println("HTTP服务器错误:" + e.getMessage()); } } } /** * 读取一个文件的内容并返回给浏览器端. * * @param fileName * 文件名 * @param socket * 客户端 socket. * @throws IOException */ void fileReaderAndReturn(String fileName, Socket socket) throws IOException { if ("/".equals(fileName)) {// 设置欢迎页面,呵呵! fileName = "/index.html"; } fileName = fileName.substring(1); PrintStream out = new PrintStream(socket.getOutputStream(), true); File fileToSend = new File(fileName); String fileEx = fileName.substring(fileName.indexOf(".") + 1); String contentType = null; // 设置返回的内容类型 // 此处的类型与tomcat/conf/web.xml中配置的mime-mapping类型是一致的。测试之用,就写这么几个。 if ("htmlhtmxml".indexOf(fileEx) > -1) { contentType = "text/html;charset=GBK"; } else if ("jpegjpggifbpmpng".indexOf(fileEx) > -1) { contentType = "application/binary"; } if (fileToSend.exists() && !fileToSend.isDirectory()) { // http 协议返回头 out.println("HTTP/1.0 200 OK");// 返回应答消息,并结束应答 out.println("Content-Type:" + contentType); out.println("Content-Length:" + fileToSend.length());// 返回内容字节数 out.println();// 根据 HTTP 协议, 空行将结束头信息 FileInputStream fis = null; try { fis = new FileInputStream(fileToSend); } catch (FileNotFoundException e) { out.println("<h1>404错误!</h1>" + e.getMessage()); } byte data[]; try { data = new byte[fis.available()]; fis.read(data); out.write(data); } catch (IOException e) { out.println("<h1>500错误!</h1>" + e.getMessage()); e.printStackTrace(); } finally { out.close(); try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } else { out.println("<h1>404错误!</h1>" + "文件没有找到"); out.close(); } } void printParams(String params) throws IOException { if (params == null) { return; } String[] maps = params.split("&"); for (String temp : maps) { String[] map = temp.split("="); System.out.println(map[0] + "==" + map[1]); } } /** */ /** * 启动 HTTP 服务器 * * @param args */ public static void main(String[] args) { try { if (args.length != 1) { System.out.println("这是一个简单的web服务器 ,端口是: 80."); } else if (args.length == 1) { PORT = Integer.parseInt(args[0]); } } catch (Exception ex) { System.err.println("服务器初始化错误" + ex.getMessage()); } new SimpleHttpServer(); } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-12-09
期待浏览器内置微型web服务器时代的到来,到时候浏览器代理接收数据,js负责处理数据,就好玩了.
|
|
返回顶楼 | |
发表时间:2009-12-10
ls的不是很靠谱,服务器还是功能独立的好,不必融到浏览器中。
|
|
返回顶楼 | |
发表时间:2009-12-10
wujiazhao88 写道 ls的不是很靠谱,服务器还是功能独立的好,不必融到浏览器中。
同意~ lz的这个挺好玩的 现在就去试试~ 一会告诉你答案 |
|
返回顶楼 | |
发表时间:2009-12-10
听说apache下的 httpComponents 不错,对于理解http协议很有帮助,最近我也在弄这个,呵呵,很好玩,有时间多多交流啊
|
|
返回顶楼 | |
发表时间:2009-12-10
这个服务器段虽然采取了多线程,但是在处理时还是阻塞的,建议看一下我的tomcat的代码分析。
|
|
返回顶楼 | |
发表时间:2009-12-10
LZ等于把JAVA.NET这个包又封了下。
|
|
返回顶楼 | |
发表时间:2009-12-10
如果能把jsp变severlet的代码上来的话更好
|
|
返回顶楼 | |
发表时间:2009-12-10
lz的代码对于post请求参数好像解析的不对
|
|
返回顶楼 | |
发表时间:2009-12-10
spiritfrog 写道 lz的代码对于post请求参数好像解析的不对 把异常打印下,数组越界。
|
|
返回顶楼 | |