一直不理解Http协议,觉得很抽象很神秘,看 《how tomcat work》时看到搭建了一个简单的http服务器,发现协议其实就是对消息格式的规范,就是大家都按这个规范约定的格式发消息收消息。
1.建立sockerserver服务
ServerSocket serverSocket = null; int port = 8088; try { serverSocket = new ServerSocket(port, 1, InetAddress .getByName("127.0.0.1")); log.info("服务启动"); } catch (IOException e) { e.printStackTrace(); System.exit(1); }
2.监听相应端口
socket = serverSocket.accept(); input = socket.getInputStream(); output = socket.getOutputStream();
3.对监听到的字节进行解析
// create Request object and parse Request request = new Request(input); request.parse();
Request 实际上就是解析HTTP协议并得到资源的请求路径uri。
public void parse() { // Read a set of characters from the socket StringBuffer request = new StringBuffer(2048); int i; byte[] buffer = new byte[2048]; try { i = input.read(buffer); } catch (IOException e) { e.printStackTrace(); i = -1; } for (int j = 0; j < i; j++) { request.append((char) buffer[j]); } log.info("request head /n"+request.toString()); uri = parseUri(request.toString()); } private String parseUri(String requestString) { int index1, index2; index1 = requestString.indexOf(' '); if (index1 != -1) { index2 = requestString.indexOf(' ', index1 + 1); if (index2 > index1) return requestString.substring(index1 + 1, index2); } return null; }
4.对请求进行响应
// create Response object Response response = new Response(output); response.setRequest(request); response.sendStaticResource();
这里实际上根据request分析的uri进行资源的字节化,输出到socket的out
public void sendStaticResource() throws IOException { byte[] bytes = new byte[BUFFER_SIZE]; FileInputStream fis = null; try { File file = new File(HttpServer.WEB_ROOT, request.getUri()); if (file.exists()) { fis = new FileInputStream(file); int ch = fis.read(bytes, 0, BUFFER_SIZE); while (ch != -1) { output.write(bytes, 0, ch); ch = fis.read(bytes, 0, BUFFER_SIZE); } } else { // file not found String errorMessage = "HTTP/1.1 404 File Not Found/r/n" + "Content-Type: text/html/r/n" + "Content-Length: 23/r/n" + "/r/n" + "<h1>File Not Found</h1>"; output.write(errorMessage.getBytes()); } } catch (Exception e) { // thrown if cannot instantiate a File object System.out.println(e.toString()); } finally { if (fis != null) fis.close(); } }
可以看到其实就是简单的将资源用字节流输出。
最后提供完整的代码包(http://download.csdn.net/source/3194644),运行HttpServer.java 后可以通过浏览器访问:http://localhost:8088/index.htm 可以看到静态页面,通过后台可以看到请求的Http信息。