`

HTTP协议文本解析

阅读更多

HTTP消息是由普通ASCII文本组成。消息包括消息头和数据体部分。消息头以行为单位,每行以CRLF(回车和换行)结束,消息头结束后,额外增加一个CRLF,之后内容就是数据体部分了。

格式如图:

                                                          http协议格式

那么如果给了一段文本 http文本  我们是否有能力用java解析呢:

GET /doaction?p=123&k=3343 HTTP/1.1
Host: localhost:12345
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: name=jackey;

  下面是我用java解析这段的http协议的一段代码

 

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
/**
 * http协议解析
 * @author Mic
 *
 */
public class HttpOperator {
	/**
	 * 协议流
	 */
   private InputStream source;
   private  byte[] buf;//缓存结果
   private  int pos;//偏移
   private int start;//开始
   private int end;//结束
   private int capacity;//缓存容量
   private int lastValid;//每次取数据buf中最有一位字节的下标
   private Request request=new Request();
   public enum METHOD{
	   GET,HEAD,POST,OPTIONS,PUT,Delete,TRACE,CONNECT
   }
   public HttpOperator(int capacity) {
	 pos=0;
	 start=0;
	 end=0;
	 lastValid=-1;
	 this.capacity=capacity;
	 buf=new byte[capacity];
   }
   public HttpOperator() {
       this(4096);
   }
   /**
    *填充缓存
    */
   public boolean  fill(){
	   return fill(buf, 0, capacity);
   }
   public boolean fill(byte[] buf,int offset,int length){
	   int len=-1;
	   try {
		 len=source.read(buf, offset, length);	   
	   }catch (IOException e) {
		  System.out.println("read source failed");
		  return false;
	   }
	   start=0;
	   end=0;
	   lastValid=len==-1?-1:len-1;
	   return len!=-1;
   
   }
   public void skipSpace(){
	   do{		  
		   if(pos>=lastValid){
			   fill();
			   pos=-1;
		   }
		   pos++;
	   }while(buf[pos]==Constant.SP||buf[pos]==Constant.HT);
   }
   
   
   public void  copy(byte[] src ,int srcOff,byte[] dest,int destOff,int len){
	  //扩容
	  if((dest.length-destOff)<len){
	    byte[] newDest=new byte[dest.length*2];
	         System.arraycopy(dest, 0, newDest, 0, dest.length);
	         dest=newDest;
	  }
	  System.arraycopy(src, srcOff, dest, destOff, len);
   }
   
   
   public void parseRequestLine(){
	   boolean quit=false;
	   while(!quit){
		   skipSpace();
		   //Method
		   byte[] v_buf=new byte[1024];
		   int v_pos=0;
		   int v_len=0;
		   start=pos;
		   while(true){
			   if(buf[pos]==Constant.SP||buf[pos]==Constant.HT){
				   copy(buf, start,v_buf,v_pos,pos-start);
				   v_pos+=(pos-start);
				   v_len+=(pos-start);
				   break;
			   }   
			   end=pos;
			   pos++;
			   //判断是否用完
			  if(pos>=lastValid){
				  copy(buf, start,v_buf,v_pos,pos-start);
				  v_pos+=(pos-start);
				  v_len+=(pos-start);
				  start=pos=end=0;
				  fill();
			  }
		   }
			  try {
				request.setMethod(new String(v_buf,0,v_len,"UTF-8"));
			} catch (UnsupportedEncodingException e) {
				 System.out.println("set method failed");
				 throw  new RuntimeException(e);
			}
		
			  
		  //URI
			v_buf=new byte[1024];
			v_pos=0;
			pos--;
			skipSpace();
			start=pos;
			v_len=0;
			while(true){
				   if(buf[pos]==Constant.SP||buf[pos]==Constant.HT){
					   copy(buf, start,v_buf,v_pos,pos-start);
					   v_pos+=(pos-start);
					   v_len+=(pos-start);
					   break;
				   }   
				   end=pos;
				   pos++;
				   //判断是否用完
				  if(pos>=lastValid){
					  copy(buf, start,v_buf,v_pos,pos-start);
					  v_pos+=(pos-start);
					  v_len+=(pos-start);
					  start=pos=end=0;
					  fill();
				  }
			   }
			   try {
					request.setUri(new String(v_buf,0,v_len,"UTF-8"));
				} catch (UnsupportedEncodingException e) {
					 System.out.println("set URI failed");
					 throw  new RuntimeException(e);
				}
			   
			   //协议版本如HTTP/1.1
				v_buf=new byte[1024];
				v_pos=0;
				pos--;
				skipSpace();
				start=pos;
				v_len=0;
				while(true){
					   if(buf[pos]==Constant.LF||buf[end]==Constant.CR){
						   copy(buf, start,v_buf,v_pos,end-start);
						   v_pos+=(pos-start);
						   v_len+=(end-start);
						   quit=true;
						   break;
					   }else if(buf[pos]==Constant.HT||buf[pos]==Constant.SP){
						   skipSpace();
						   continue;
					   }
					   
					   end=pos;
					   pos++;
					   //判断是否用完
					  if(pos>=lastValid){
						  copy(buf, start,v_buf,v_pos,pos-start);
						  v_pos+=(pos-start);
						  v_len+=(pos-start);
						  start=pos=end=0;
						  fill();
					  }
				   }
					  try {
						request.setHttpVersion(new String(v_buf,0,v_len,"UTF-8"));
					} catch (UnsupportedEncodingException e) {
						 System.out.println("set HttpVersion failed");
						 throw  new RuntimeException(e);
					}
				
		   }
}
   public void parseRequestHeaders(){
	   while(parseRequestHeader()){
		   
	   }
   }
   private boolean parseRequestHeader(){
	   boolean quit=true;
		   skipSpace();
		   //Method
		   byte[] v_buf=new byte[1024];
		   int v_pos=0;
		   int v_len=0;
		   start=pos;
		   //name
		   HttpHeader httpHeader=null;
		   while(true){
			   if(buf[pos]==Constant.COLON){
				   copy(buf, start,v_buf,v_pos,pos-start);
				   v_pos+=(pos-start);
				   v_len+=(pos-start);
				   break;
			   }   
			   end=pos;
			   pos++;
			   //判断是否用完
			  if(pos>=lastValid){
				  copy(buf, start,v_buf,v_pos,pos-start);
				  v_pos+=(pos-start);
				  v_len+=(pos-start);
				  start=pos=end=0;
				  fill();
			  }
		   }
		   try {
			httpHeader=HttpHeader.addHeaderName(new String(v_buf,0,v_len,"UTF-8"));
		} catch (UnsupportedEncodingException e1) {
		    return false;
		}
	     //Value
				v_buf=new byte[1024];
				v_pos=0;
				skipSpace();
				start=pos;
				v_len=0;
				while(true){
					   if(buf[pos]==Constant.LF||buf[end]==Constant.CR){
						   copy(buf, start,v_buf,v_pos,end-start);
						   v_pos+=(pos-start);
						   v_len+=(end-start);
						   break;
					   }else if(buf[pos]==Constant.HT||buf[pos]==Constant.SP){
						   skipSpace();
						   continue;
					   }
					   
					   end=pos;
					   pos++;
					   //判断是否用完
					  if(pos>=lastValid){
						  copy(buf, start,v_buf,v_pos,pos-start);
						  v_pos+=(pos-start);
						  v_len+=(pos-start);
						  start=pos=end=0;
						  fill();
					  }
				   }
			 try {
				   httpHeader.setValue(new String(v_buf,0,v_len,"UTF-8"));
			 	} catch (UnsupportedEncodingException e) {
						 System.out.println("set HttpVersion failed");
						 throw  new RuntimeException(e);
		  }
			 request.addHeader(httpHeader);
			 //是否完成
			if(pos>=lastValid){
				  start=pos=end=0;
				  fill();
			}
			if(buf[pos+1]==Constant.CR||buf[pos+2]==Constant.LF){
				quit=false;
				pos+=3;
			}
	   return quit;
}
 
  public void parseRequestBody(){
    	if(pos<=lastValid){
    		byte[] body=new byte[1024];
    		copy(buf, pos,body,0,lastValid-pos+1);
    		while(fill(buf, 0, capacity)){
    			  copy(buf, 0,body,0,lastValid+1);	
    		}
    		request.setBody(body);
    	} 
    	
  }
   
   
public InputStream getSource() {
	return source;
}
public void setSource(InputStream source) {
	this.source = source;
}
public Request getRequest() {
	return request;
}
public void setRequest(Request request) {
	this.request = request;
}
	   
	   
   }
 

 HttpOperator 用来来解析http协议的一个类,其中三个关键方法:parseRequestLine 请求行的解析,parseRequestHeaders 请求头解析,parseRequestBody请求包体解析

 

而解析后的内容用Request来封装

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 所获得的请求
 * @author Mic
 *
 */
public class Request implements Serializable{
 //请求方法
 private String method;
 //协议版本
 private String httpVersion;
 //uri
 private String uri;
 //域头
 private List<HttpHeader> httpheaders;
 //body
 private byte[] body;
public String getMethod() {
	return method;
}
public void setMethod(String method) {
	this.method = method;
}

public String getHttpVersion() {
	return httpVersion;
}
public void setHttpVersion(String httpVersion) {
	this.httpVersion = httpVersion;
}
public String getUri() {
	return uri;
}
public void setUri(String uri) {
	this.uri = uri;
}
public List<HttpHeader> getHttpheaders() {
	return httpheaders;
}
public void setHttpheaders(List<HttpHeader> httpheaders) {
	this.httpheaders = httpheaders;
}
public byte[] getBody() {
	return body;
}
public void setBody(byte[] body) {
	this.body = body;
}
 
public void addHeader(HttpHeader header){
	if(httpheaders==null) httpheaders=new ArrayList<HttpHeader>();
	httpheaders.add(header);
}
public void addHeader(String name,Object value){
	if(httpheaders==null) httpheaders=new ArrayList<HttpHeader>();
	httpheaders.add(new HttpHeader(name,value));
}
}

 下面是其他的一些附加类

public class Constant {
  /**
  * CRLF.
  */
  public final static String CRLF="\r\n";
  /**
   * CR.
   */
  public final static byte CR=(byte)'\r';
  /**
   * LF
   */
  public final static byte LF=(byte) '\n';
  /**
   * SP.
   */
  public final static byte SP=(byte) ' ';
  /**
   * HT.
   */
  public final static byte HT=(byte) '\t';
  /**
   * COLON.
   */
  public final static byte COLON=(byte) ':';
  /**
   * SEMI_COLON
   */
  public final static byte SEMI_COLON=(byte) ';';
  

  /**
   * 'A'.
   */
  public static final byte A = (byte) 'A';


  /**
   * 'a'.
   */
  public static final byte a = (byte) 'a';


  /**
   * 'Z'.
   */
  public static final byte Z = (byte) 'Z';

 

public class HttpHeader {
  private String name;//域头名
  private Object value;//域头值
  public String getName() {
		return name;
  }
  
  public HttpHeader(String name, Object value) {
	super();
	this.name = name;
	this.value = value;
}

public HttpHeader(String name) {
	super();
	this.name = name;
}

public void setName(String name) {
		this.name = name;
   }
   public Object getValue() {
		return value;
   }
   public void setValue(Object value) {
		this.value = value;
  }
  public static HttpHeader addHeaderName(String name){
	  return new HttpHeader(name);
  }

@Override
public String toString() {
	return "HttpHeader [name=" + name + ", value=" + value + "]";
}
 
}

 通过上述类我做了一段测试代码如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

public class HttpOperatorTest {
	HttpOperator operator;
	@Before
	public void setup() throws FileNotFoundException{
		operator=new HttpOperator(1024);
		FileInputStream fis=new FileInputStream(new File(System.getProperty("user.dir"),"resource/httpRequest.txt"));
		operator.setSource(fis);
	}
	@Test
	public void test() {
	    operator.parseRequestLine();
	    Request request=operator.getRequest();
	    System.out.println("Method:"+request.getMethod());
	    System.out.println("URI:"+request.getUri());
	    System.out.println("HttpVersion:"+request.getHttpVersion());
	    System.out.println("=====================parseHeaders=====");
	    operator.parseRequestHeaders();
	   List<HttpHeader> httpHeaders=request.getHttpheaders();
	   if(httpHeaders!=null&&! httpHeaders.isEmpty()){
		   for(HttpHeader header:httpHeaders)
			   System.out.println(header.getName()+":"+header.getValue());
	   }
	   operator.parseRequestBody();
	   System.out.println("=====================parseBody=====");
	   System.out.println(Arrays.toString(request.getBody()));
	}

}

 测试结果如下:

测试结果 写道
Method:GET
URI:/doaction?p=123&k=3343
HttpVersion:HTTP/1.1
=====================parseHeaders=====
Host:localhost:12345
Connection:keep-alive
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie:name=jackey;
=====================parseBody=====
null

 

  • 大小: 87.1 KB
分享到:
评论

相关推荐

    HTTP 协议 的解析 HTTP 协议 的解析

    **HTTP协议解析** HTTP(Hypertext Transfer Protocol)超文本传输协议是互联网上应用最广泛的一种网络协议。它是Web浏览器和服务器之间通信的基础,用于在万维网上传输数据。HTTP协议是基于TCP/IP协议之上的应用层...

    HttpCommunications_HTTP通讯协议解析_

    本主题将深入解析HTTP协议,包括GET和POST两种主要的请求方法。 首先,HTTP(超文本传输协议)基于TCP/IP协议栈,工作在应用层。它的基本工作流程是客户端向服务器发送一个请求,请求中包含要执行的动作和所需资源...

    http 协议解析器

    **HTTP协议解析器详解** HTTP(HyperText Transfer Protocol)协议是互联网上应用最为广泛的一种网络协议,用于从万维网服务器传输超文本到本地浏览器的传输协议。它是一个基于请求与响应模型的、无状态的、应用层...

    http协议解析软件C源码

    在这个“http协议解析软件C源码”中,我们主要可以学习以下几个关键知识点: 1. **HTTP协议基础**:理解HTTP的基本工作原理,包括请求方法(GET、POST等)、状态码(200、400、500等)、头信息(如User-Agent、...

    全面解析HTTP协议

    《全面解析HTTP协议》 HTTP(Hypertext Transfer Protocol)协议是互联网上应用最广泛的一种网络协议,用于在客户端和服务器之间传输超文本信息。它最初设计时是为了解决分布式、合作式的多媒体信息系统的需求,...

    HTTP 上载文件协议解析

    HTTP(超文本传输协议)是互联网上应用最为广泛的一种网络协议,用于从万维网服务器传输超媒体文档至客户端。当涉及到文件上传时,HTTP 协议提供了一种方法,允许用户通过Web浏览器将文件从本地系统传送到远程服务器...

    Http.rar_HTTP java_HTTP协议_http解析

    HTTP协议的解析涉及到URL解码、编码,状态码的处理,请求头和响应头的理解,以及数据的序列化和反序列化。在Java中,这些可以通过各种库或者自定义解析逻辑来实现。例如,对于JSON格式的数据,可以使用Jackson或Gson...

    超文本传输协议HTTP中文

    - **无状态**:HTTP协议本身是无状态的,即每次请求都是独立的,不保存历史信息。 - **简单**:HTTP的设计简洁明了,易于实现。 - **可扩展性**:可以通过添加新的字段来扩展协议的功能。 - **支持多种媒体类型**:...

    HTTP协议详解_HTTP协议_

    HTTP协议的工作原理: 1. 请求过程:当用户在浏览器中输入URL并按下回车键时,浏览器作为客户端(Client)构造一个HTTP请求报文,包括方法(GET、POST等)、URL、协议版本、头部信息和请求主体(如果有的话)。然后...

    协议解析工具

    在协议解析的上下文中,ASCII(美国标准信息交换代码)通常是指纯文本文件,它使用7位的ASCII码来表示字符,是网络通信中最基础的数据形式之一。 协议解析工具的核心功能包括: 1. **捕获网络流量**:工具通过监听...

    http超文本传送协议

    HTML文档通过HTTP协议在浏览器和服务器之间传递,浏览器解析这些文档并呈现给用户。 在实际应用中,HTTP不仅用于Web浏览,还被广泛应用于其他服务,如API接口、文件下载、流媒体等。随着互联网的发展,HTTP协议不断...

    基于http协议的自定义协议封装

    本文将深入探讨基于HTTP协议的自定义协议封装,特别是在使用XML作为数据载体时如何进行设计和实现。HTTP(超文本传输协议)是互联网上应用最为广泛的一种网络协议,它允许客户端(如浏览器)和服务器之间交换数据。...

    使用labview的http协议post 和get ,带解析

    1.网页打不开的post不了,不存在的属性post不了,属性不区分大小写 2.post模式下内容格式要对,=赋值不能少 3.get模式下url=不能少 4.header 200表示响应成功,post 的内容要用web services readpostdata,两个VI...

    超文本传输协议

    ### 超文本传输协议(HTTP)实验报告关键...通过这些实验和分析,学生不仅能够深入理解HTTP协议的核心概念和技术细节,还能掌握如何在实际网络环境中应用这些知识,为进一步学习高级网络技术和网络安全打下坚实的基础。

    VS2012 Qt5 winpcap win64 抓包工具 http协议 解析

    6. **HTTP协议解析**:HTTP(超文本传输协议)是互联网上应用最广泛的一种网络协议,用于客户端(浏览器)和服务器之间的通信。解析HTTP协议涉及理解请求和响应的结构、状态码、头信息等,这对于开发Web应用、网络...

    ry-http.rar_C++ HTTP解析_c语言 http_http 解析 C语言_http解析_解析 http

    《C语言实现HTTP解析器详解》 ...提供了一个用C语言实现的HTTP解析器,适用于开发需要处理HTTP协议的系统。通过深入理解和使用这个解析器,开发者可以更好地驾驭HTTP通信,提升应用系统的稳定性和效率。

    VC通过Http协议Get或Post方式与WebService通信,解析返回的Json.zip

    在IT行业中,尤其是在软件开发领域,使用HTTP协议与Web服务进行通信是常见的操作。本教程主要探讨如何在C++环境下,利用Wininet库通过HTTP GET和POST方法与WebService交互,并解析返回的JSON数据。让我们深入了解...

    松哥解协议松哥解协议松哥解协议松哥解协议松哥解协议

    在协议解析中,这可能用于显示和处理协议中的文本数据,尤其是涉及多语言或特殊字符的情况。 3. 八学研究协会解mavlink.exe:这可能是一个专门用来解析Mavlink协议的工具,由"八学研究协会"开发。Mavlink是一种轻量...

    超文本传输协议工作原理.docx

    - **HTTPS**:为了提高安全性,HTTP协议可以通过加入SSL/TLS加密层升级为HTTPS协议,这样可以保护数据的完整性和机密性,防止中间人攻击。 #### 七、HTTP与其他网络协议的关系 尽管TCP/IP协议是互联网上最常用的...

    Winpcap解析HTTP报文头

    通过这种方式,Winpcap结合对TCP和HTTP协议的理解,可以帮助我们深入洞察网络流量,对HTTP应用的行为进行监控、调试或分析。对于网络开发者、安全专家和系统管理员来说,这是一项非常有价值的技能。在实际操作中,...

Global site tag (gtag.js) - Google Analytics