前言
之前的一次课设上面做了一个作业。其中的java不使用tomcat来进行通信的部分。
首先来说一说“java实现简单的http服务器”这个东西是什么意思。我们使用浏览器进行访问时我们是客户端,向服务器寻求我们需要的网页资料。
我们打开的html网页,这是一个静态的文件,还有一众Css文件,js文件以及图片文件等等。我们通过向服务器发送get等方式的请求进行获取,然后接受服务器发回来的文件,通过浏览器的组织和加载之后就可以得到我们所看到的网页的内容了。
我们服务器是通过输入一个网址(URL)来进行内容的定位,然后发送过去一些http请求,服务器上有一个服务来对这些http请求进行处,查找客户端所需要的内容。将这些内容反馈发给客户端。
预备知识提纲
首先需要了解HTTP协议,我们不使用tomcat服务器,不使用Java已经封装好的HttpServlet类来进行get方法以及post方法的反馈。我们写的这个功能就是自主实现了非常小的tomcat的功能。
因为我们的网络通信都是基于socket的,仔细想一下,其实所有的内容都是通过socket完成的。浏览器之所以能够进行数据的传输是因为使用80端口(Apache等使用的端口),所有的软件的使用都是通过socket的传输数据在应用层上进行了内容的开发,然后完成的某些功能成为了一个应用(个人拙见)。我们这里要做的就是通过8080端口(Tomcat使用的端口)来完成原本tomcat的工作。
socket基本使用
这个东西也就不多讲了吧。java基础,在C语言里面socket只有一种数据结构类型,使用的时候分为Server的socket和普通的socket使用。但是在java由于比较好的封装性分为ServerSocket和Socket两个类,照着写就差不多了。
HTTP协议
这个协议比较重要,因为在B/S架构下浏览器和服务器之间的数据传递是根据HTTP协议来完成的。需要了解http的发送和接收的报文结构,还有响应结构,如下图所示。
可以参照下面教程的例子进行学习。在我们的实现中不需要写太多的报文首部内容,能够让浏览器进行正确的识别即可。学习内容如下
- HTTP报文格式 //HTTP的基本报文格式
- GET,POST报文格式 //其实就是信息放在url和放在最后的区别
菜鸟教程写的还不错->点我跳转
代码部分
主要调用的地方在第73行来完成我的工作。其他的部分就是通过报文格式来发送文件给浏览器进行组织和呈现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
| import java.io.*; import java.net.*; import java.util.StringTokenizer;
public class SimpleHttpServer implements Runnable {
ServerSocket serverSocket; public static int PORT=8080;
public SimpleHttpServer() { try { serverSocket=new ServerSocket(PORT); } catch(Exception e) { System.out.println("无法启动HTTP服务器:"+e.getLocalizedMessage()); } if(serverSocket==null) System.exit(1); new Thread(this).start(); System.out.println("HTTP服务器正在运行,端口:"+PORT); } public void run() { while(true) { try { Socket client=null; client=serverSocket.accept(); if(client!=null) { System.out.println("连接到服务器的用户:"+client); try { BufferedReader in=new BufferedReader(new InputStreamReader( client.getInputStream())); System.out.println("客户端发送的请求信息: ***************"); String line=in.readLine(); System.out.println(line); String resource=line.substring(line.indexOf('/')+1,line.lastIndexOf('/')-5); resource=URLDecoder.decode(resource, "UTF-8"); String method = new StringTokenizer(line).nextElement().toString();
while( (line = in.readLine()) != null) {
if(line.equals("")) break; } System.out.println("请求信息结束 ***************"); System.out.println("用户请求的资源是:"+resource); System.out.println("请求的类型是: " + method);
if(resource.equals("")&&method.equals("GET")){ String ConTentType="Content-Type: text/html;charset=UTF-8"; fileService("WebContent/index.html",client,ConTentType); closeSocket(client); } if(resource.endsWith(".js")&&method.equals("GET")) { String ConTentType="Content-Type: application/javascript;charset=UTF-8"; fileService("WebContent/"+resource, client,ConTentType); closeSocket(client); continue; } } catch(Exception e) { System.out.println("HTTP服务器错误:"+e.getLocalizedMessage()); } } } catch(Exception e) { System.out.println("HTTP服务器错误:"+e.getLocalizedMessage()); } } } void closeSocket(Socket socket) { try { socket.close(); } catch (IOException ex) { ex.printStackTrace(); } System.out.println(socket + "离开了HTTP服务器"); }
void fileService(String fileName, Socket socket,String ConTentType) { try { PrintStream out = new PrintStream(socket.getOutputStream(), true); File fileToSend = new File(fileName); if(fileToSend.exists() && !fileToSend.isDirectory()) { out.println("HTTP/1.0 200 OK"); out.println(ConTentType); out.println("Content-Length: " + fileToSend.length()); out.println();
FileInputStream fis = new FileInputStream(fileToSend); byte data[] = new byte[fis.available()]; fis.read(data); out.write(data); out.close(); fis.close(); } }catch(Exception e){ System.out.println("传送文件时出错:" + e.getLocalizedMessage()); } } private static void usage() { System.out.println("Usage: java HTTPServer <port> Default port is 80."); }
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("Invalid port arguments. It must be a integer that greater than 0"); } new SimpleHttpServer(); } }
|
后记
如果对具体的实例想自己操作一下,我的内容放在github上面,第一次做写的有点烂–>socket-web分支
这个分支就是把之前的那个{% post_link JavaScript/java-web遗传算法最短路径规划 %}
不用tomcat,使用socket来完成的。
emm…这篇貌似写的挺粗略的,懒得写了。要研究下的可以直接去给gayhub看代码吧。关键就是理解http协议的格式,并不难。
参考资料
这篇文章给了很大的帮助,实现了很大的一部分功能
http://blog.csdn.net/overmaker/article/details/2194921
当然需要掌握的只是还有Socket和http协议,我还看了一下《图解HTTP》这本书的内容
菜鸟教程的HTTP内容
http://www.runoob.com/http/http-messages.htmls