HTTP协议包读取过程的Java实现

网络 网络管理
首先我们在了解了前文的基础后,再来对读取HTTP协议包的代码进行一下讲解。那么这部分内容的代码比较多,希望能够帮助大家了解这部分内容。

之前的两篇文章中《GET实现HTTP协议请求包的分析》和《HTTP协议请求包的Java实现》对HTTP协议包的请求连接内容进行了不少的讲解。那么本文将继续做一下补充,主要是讲解如何完成读取HTTP包。

以下我自己设计的一个读取HTTP协议包的类SocketRequest。

public class SocketRequest   
{//从指定的Socket的InputStream中读取数据  
private InputStreaminput;  
private Stringuri;  
private StringBufferrequest=new StringBuffer();//用于保存所有内容  
private intCONTENT_LENGTH=0;//实际包内容数据长  
private boolean bePost = false;  
private boolean beHttpResponse = false;  
private boolean beChucked = false;  
private boolean beGet = false;  
private bytecrlf13 = (byte)13; //'r'  
private bytecrlf10 = (byte)10;//'n'  
public SocketRequest(InputStream input) {  
this.input = input;}  
public SocketRequest(Socket socket) {  
this.input = socket.getInputStream();}  
public void ReadData()   
{//解析 获得InputStream的数据   
ReadHeader();//头部  
if(beChucked) //为Chucked  
{int ChuckSize=0;  
while((ChuckSize=getChuckSize())>0) //多个Chucked  
{readLenData(ChuckSize+2);//读取定长数据}  
readLenData(2); //最后的2位}  
if(CONTENT_LENGTH>0)  
{readLenData(CONTENT_LENGTH);//读取定长数据}  
uri = "";//parseUri(new String(request));}  
private void readLenData(int size)//读取定长数据  
{int readed=0;//已经读取数  
try{  
int available=0;//input.available(); //可读数  
if(available>(size-readed)) available=size-readed;  
while( readed<size )  
{while(available==0){//等到有数据可读  
available = input.available(); //可读数}  
if(available>(size-readed)) available= size-readed; //size-readed--剩余数  
if(available>2048) available= 2048; //size-readed--剩余数  
byte[] buffer = new byte[available];  
int reading = input.read(buffer);  
request=request.append(new String(buffer,0,reading));//byte数组相加  
readed+=reading;//已读字符  
}}catch(IOException e){System.out.println("Read readLenData Error!");} }   
private voidReadHeader() //读取头部 并获得大小  
{byte[]crlf= new byte[1];  
intcrlfNum= 0;//已经连接的回车换行数 crlfNum=4为头部结束  
try{while( input.read(crlf)!=-1 )//读取头部  
{if(crlf[0]==crlf13 || crlf[0]==crlf10)  
{crlfNum++; }  
else 
{crlfNum=0;} //不是则清  
request=request.append(new String(crlf,0,1));//byte数组相加  
if(crlfNum==4) break;}}  
catch(IOException e){System.out.println("Read Http Header Error!");  
return;}  
String tempStr=(new String(request)).toUpperCase();//这里我只处理了GET与POST方法  
StringstrMethod= tempStr.substring(0,4);  
if(strMethod.equals("GET ")) //前  
{beGet=true;}  
else if(strMethod.equals("POST"))  
{bePost=true;  
getContentlen_Chucked(tempStr);}  
else {System.out.println("不支持的HTTP协议包类型");}//其它的其它类型 暂不支持  
}  
private void getContentlen_Chucked(String tempStr)//获得长度 CONTENT-LENGTH 或 是否为CHUNKED型  
{String ss1="CONTENT-LENGTH:";  
String ss2=new String("TRANSFER-ENCODING: CHUNKED");  
int clIndex= tempStr.indexOf(ss1);  
int chuckIndex = tempStr.indexOf(ss2);//为CHUNKED型  
byte requst[]= tempStr.getBytes();  
if(clIndex!=-1)  
//从clIndex+1起至rn  
StringBuffer sb=new StringBuffer();  
for(int i=(clIndex+16);;i++)  
{if(requst[i]!=(byte)13 && requst[i]!=(byte)10 )  
{sb.append((char)requst[i]);}  
else   
break;}  
CONTENT_LENGTH=Integer.parseInt(sb.toString());//正式的HTML文件的大小  
//System.out.println("CONTENT_LENGTH=="+CONTENT_LENGTH);}  
if(chuckIndex!=-1) beChucked=true;}  
private intgetChuckSize() //Chuck大小{  
byte[]crlf= new byte[1];  
StringBuffersb1= new StringBuffer();  
intcrlfNum= 0;//已经连接的回车换行数 crlfNum=4为头部结束  
try{while(input.read(crlf)!=-1)//读取头部{  
if(crlf[0]==crlf13 || crlf[0]==crlf10)  
{crlfNum++; }  
else 
{crlfNum=0;} //不是则清  
sb1.append((char)crlf[0]);  
request=request.append(new String(crlf,0,1));//byte数组相加  
if(crlfNum==2) break;}  
}catch(IOException e){  
System.out.println("Read Http Package Error!");  
return 0;}  
return Integer.parseInt((sb1.toString()).trim(),16); //16进控制  
}//通过此来进行过滤,是否为发至目标服务器的HTTP协议包  
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;}  
public String getData() {  
return request.toString();}} 
  • 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.

使用此类:

SocketRequest request = new SocketRequest(socket); //socket为ServerSocket.accept()返回的Socket实例  
request.ReadData();//读取数据  
request.getData(); 
  • 1.
  • 2.
  • 3.

为什么我要用这么大的力量去读取呢,尤其是在因为Socket连接在发送数据时,由于网络的原因经常会发生延迟现象,可能在服务器端开始接收数据时可能只有部分数据可以从InputStream中获得,在一些地方处理不当时,可能只能获得不完整的数据或是错误的数据。

从InputStream读取字节时有多种办法:

常用int read()与int read(byte[] b)。在用read(byte[])时,程序员经常会犯错误,因为在网络环境中,读取的数据量不一定等于参数的大小。

责任编辑:佟健 来源: 网界网
相关推荐

2010-06-29 13:24:26

HTTP协议

2010-06-29 13:18:31

HTTP协议

2020-06-17 21:39:11

HTTP协议服务器

2019-04-08 15:11:12

HTTP协议Web

2010-06-24 13:18:38

ICMP协议

2018-04-17 16:29:24

Java面试HTTP

2019-08-01 15:25:17

Http服务器协议

2014-10-22 09:36:41

TCPIP

2021-03-05 11:20:24

HTTPWebshellWeb服务器

2015-10-09 15:07:02

HTTP网络协议

2017-05-26 10:35:13

前端HTTP

2018-10-18 10:05:43

HTTP网络协议TCP

2015-09-15 13:48:01

网络协议HTTP Client

2010-07-01 16:01:05

HTTP协议

2010-06-08 12:31:15

HTTP协议实体

2010-09-09 13:09:33

协议栈开发

2010-06-23 14:27:04

Fix协议

2011-09-06 09:48:41

MTK平台

2022-03-09 18:54:30

HTTP缓存协议cache

2019-08-23 06:36:32

点赞
收藏

51CTO技术栈公众号