之前的两篇文章中《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[])时,程序员经常会犯错误,因为在网络环境中,读取的数据量不一定等于参数的大小。