zoukankan      html  css  js  c++  java
  • Android版Web服务器实现(一)HTTP协议请求头解析

    Web服务器是可以向发出请求的浏览器提供文档的程序,主要功能是提供网上信息浏览服务。不论在哪里的浏览器向服务端发出了请求,服务端只有收到了请求之后才会作出响应。那么服务端又要如何知道有请求发来呢?最简单的方法莫过于监听。对于服务端的机器上,能够用来监听的就是端口,所以根本上,服务端是通过监听某个端口,然后当浏览器向这个端口发出请求后,服务端就能收到信息,再作出相应的响应。

    浏览器要向服务端发出请求,那么必须先建立一个通讯的通道,这个通道一般是TCP连接。当与服务端建立TCP连接之后,就可以发出请求。那么这个请求是怎么构成的呢?这就需要一个约定的协议,即HTTP协议。

    HTTP协议是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。用Chrome浏览网页的时候,按下F12,然后点到NetWork的区域中,再浏览网页,这时会显示一系列的请求信息。下面是一个截图。


    从图中可以看到,有两大部分,第一部分是Request Headers,是浏览器发起的请求头,这里我们主要关注是请求的方法、请求的资源路径、请求的HTTP版本。

    第二部分是Response Headers,是服务器回应的信息头,这里我们主要关注的是HTTP版本及状态码、响应的数据类型和字符集、数据长度。对于数据长度部分,可以参看这篇文章《HTTP协议中Content-Length的详细解读》。

    我们需要构建WEB服务器,第一步是对Request Headers的解析,第二步是构建Response Headers,第三步是发送数据。

    在解析Request Headers时,首先要看是什么样的请求方法,常见的是GET/POST,在解析出请求方法后,再解析请求的资源路径,至于HTTP版本,现在一般都是1.1的,可以暂时不作解析。

    下面解析的代码:

    HttpHeader.java

    package com.sparkle.webservice;
    
    
    public class HttpHeader {
    
    	private String _method = "";
    	private String _url = "";
    	private String _fileName = "";
    	private String _contentType = "text/html";
    
    	public String getMethod() {
    		return _method;
    	}
    
    	public String getUrl() {
    		return _url;
    	}
    
    	public String getFileName() {
    		return _fileName;
    	}
    
    	public String getContentType() {
    		return _contentType;
    	}
    
    	public HttpHeader(String headerStr) {
    		analy(headerStr);
    	}
    
    	private void analy(String headerStr) {
    		if (headerStr == null || headerStr.length() <= 0) {
    			return;
    		}
    
    		// Method
    		_method = headerStr.substring(0, headerStr.indexOf(" "));
    
    		// Url
    		int start = headerStr.indexOf(_method) + _method.length() + 1;
    		int end = headerStr.lastIndexOf("HTTP") - 1;
    		_url = headerStr.substring(start, end);
    
    		// File name and content type
    		_fileName = _url.replace("/", "\").replace("\..", "")
    				.replace("\", "/");
    		start = _fileName.lastIndexOf('.') + 1;
    		String fileSuffix = "";
    		if (start <= 0) {
    			_fileName = Defaults.getIndexPage();
    			start = _fileName.lastIndexOf('.') + 1;
    		}
    
    		fileSuffix = _fileName.substring(start);
    
    		//Log.e("File", _fileName);
    		_contentType = Defaults.Extensions.get(fileSuffix);
    	}
    }
    
    注:

    1、解析出请求方法、请求的资源。

    2、根据请求资源的文件名后缀,获取回应的文件类型。如果有需要增加的类型,可以在列表中增加。列表见下面的代码。

    Defaults.java

    package com.sparkle.webservice;
    
    import java.util.HashMap;
    
    import android.content.Context;
    import android.os.Environment;
    
    public class Defaults {
    
    	@SuppressWarnings("serial")
    	public static HashMap<String, String> Extensions = new HashMap<String, String>() {
    		{
    			put("htm", "text/html");
    			put("html", "text/html");
    			put("xml", "text/xml");
    			put("txt", "text/plain");
    			put("json", "text/plain");
    			put("css", "text/css");
    			put("ico", "image/x-icon");
    			put("png", "image/png");
    			put("gif", "image/gif");
    			put("jpg", "image/jpg");
    			put("jpeg", "image/jpeg");
    			put("zip", "application/zip");
    			put("rar", "application/rar");
    			put("js", "text/javascript");
    		}
    	};
    
    	private static String _root = Environment.getExternalStorageDirectory()
    			.getAbsolutePath();
    	private static String _indexPage = "index.html";
    	private static int _port = 8080;
    	private static String _settingsName = "WebService";
    	@SuppressWarnings("deprecation")
    	private static int _settingsMode = Context.MODE_WORLD_WRITEABLE;
    
    	public static String getRoot() {
    		if (_root == null || _root.length() <= 0) {
    			_root = Environment.getExternalStorageDirectory().getAbsolutePath();
    		}
    
    		if (!_root.endsWith("/")) {
    			_root += "/";
    		}
    		return _root;
    	}
    
    	public static void setRoot(String root) {
    		_root = root;
    	}
    
    	public static String getIndexPage() {
    		return _indexPage;
    	}
    
    	public static void setIndexPage(String indexPage) {
    		_indexPage = indexPage;
    	}
    
    	public static int getPort() {
    		return _port;
    	}
    
    	public static void setPort(int port) {
    		_port = port;
    	}
    
    	public static String getSettingsName() {
    		return _settingsName;
    	}
    
    	public static void setSettingsName(String settingsName) {
    		Defaults._settingsName = settingsName;
    	}
    
    	public static int getSettingsMode() {
    		return _settingsMode;
    	}
    
    	public static void setSettingsMode(int settingsMode) {
    		Defaults._settingsMode = settingsMode;
    	}
    }
    
    关于HTTP协议详解,可以参看此文《HTTP协议详解(很详细)
    转载请注明出处: 

    Android版Web服务器实现(一)HTTP协议请求头解析

  • 相关阅读:
    WPF TreeView IsExpanded 绑定不上的问题
    WPF TreeView BringIntoViewBehavior
    WPF ListBox的进阶使用(二)
    WPF ListBox的进阶使用(一)
    双缓冲队列解决WPF界面卡死
    C# 对接Https接口
    软件架构的六大设计原则
    FeignClient接口封装
    CentOS修改root密码
    并发编程的挑战(Java并发编程的艺术)
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7605028.html
Copyright © 2011-2022 走看看