HTTP协议分析

来源:互联网 发布:js如何解析json数组 编辑:程序博客网 时间:2024/04/28 03:12

对HTTP协议进行分析:
测试环境:
WIN 2K -SP4
Apache/1.3.29 (Win32)
IE 6.0
Firefox/1.0

测试步骤:
1:先建立TCP连接。
2:发送如下请求:

GET /index.html HTTP/1.1
Accept:*?*
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host:192.168.0.119
Connection: Keep-Alive

3:如后接受数据:
接受到的的结构如下:  HTTP协议回应 + 网页正文 + HTTP的结尾结构

//------------------------------------------------------------------------具体数据如下
HTTP/1.1 200 OK

Date: Mon, 19 Dec 2005 10:51:54 GMT

Server: Apache/1.3.29 (Win32)

Last-Modified: Tue, 16 Mar 2004 12:24:28 GMT

ETag: "0-dab-4056f1fc"

Accept-Ranges: bytes

Content-Length: 3499

Keep-Alive: timeout=30, max=100

Connection: Keep-Alive

Content-Type: text/html


//**************************************网页正文(略)


HTTP/1.1 414 Request-URI Too Large

Date: Mon, 19 Dec 2005 10:51:54 GMT

Server: Apache/1.3.29 (Win32)

Connection: close

Content-Type: text/html; charset=iso-8859-1









Request-URI Too Large
The requested URL's length exceeds the capacity
limit for this server.

request failed: URI too long





--------------------------------------------------------------------------------


Apache/1.3.29 Server at localhost Port 8080



//------------------------------------------------------------------------数据结束

这之间还要有一个地方值得注意的就是当发出请求后,服务器回送数据时是分段发送的。
比如Apache/1.3.29 (Win32)返回一个大网页数据的时候就发送了5个包
1,2,3,4包是4098字节,最后剩下的数据由第5个包返回是1953个字节。
这5个包的数据结构如下:
1包:HTTP回应头结构 + 网页正文
2包:网页正文
3包:网页正文
4包:网页正文
5包:网页正文 + HTTP回应结尾结构


今天上午大哥说的东西其实就是这样一个东西:
1:SERVER开一个端口80。
2:CLIENT 连接 SERVER 用TCP协议,然后提出一个HTTP请求。
3:CLIENT 接收 SERVER 的数据,结构:HTTP回应头结构 + 文件内容 + HTTP回应结尾结构


从这些我们基本就可以看出来HTTP协议是建立在TCP协议之上。协议的请求和回应的结构也不是很严格。
这点和TCP,UDP等协议比较起来,HTTP协议并不像TCP/UDP等协议严格。
其实如果要较细致的学习这个协议,主要就是学习请求和回应的格式。


这是我截获的 IE6.0 的HTTP请求,访问命令:http://192.168.0.119:800

GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, *?*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Host: 192.168.0.119:800
Connection: Keep-Alive

这是我截获的 firefox 的HTTP请求,访问命令:http://192.168.0.119:800

GET / HTTP/1.1
Host: 192.168.0.119:800
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.7.5) Gecko/20041224 Firefox/1.0
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*?*;q=0.5
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive



注:以上请求里面有都一个*?*,其实这“?”应该是“/”  原因是因为是程序里面的注释符号



今天就着昨天的研究成果上面又具体的看了一下,还那昨天的那5个包做例子:

这之间还要有一个地方值得注意的就是当发出请求后,服务器回送数据时是分段发送的。
比如Apache/1.3.29 (Win32)返回一个大网页数据的时候就发送了5个包
1,2,3,4包是4098字节,最后剩下的数据由第5个包返回是1953个字节。

(info_php.php)
这5个包的数据结构如下:
1包4098:HTTP回应头结构 + 5个字节的数据() +  网页正文
2包4098:5个字节的数据()  +  网页正文
3包4098:5个字节的数据()  +  网页正文
4包4098:5个字节的数据()  +  网页正文
5包1953:5个字节的数据()  +  网页正文 +  5个字节的数据(通常是0) + HTTP回应结尾结构 + 网页结构


以上是对大于两个分段的网页的测试:(index.htm)
两个分段的网页:
1包4096:HTTP回应头结构 + 网页正文 + HTTP回应结尾结构 + 网页结构(一半)
2包195:网页结构(另一半)

以上是对大于一个分段的网页的测试:(index.html)
1包949: HTTP回应头结构 + 网页正文 + HTTP回应结尾结构 + 网页结构

一点小小的疑惑:当我测试普通的网页(*.html)反回分段时没有那5个字节的数据。
但当我测试动态网页(*.php)时在里面有那5个字节的数据,我不明白是不是里面还有什么别的机制来控制
HTTP协议的数据分段。另外说一点就是,那个5个字节的数据是16进制的数据。
大概是代表本分段里面的网页正文数据的字节数。

相信HTTP协议里面还有我没有发现的东西,但基本的东西我想我这里面写应该差不多了!

下面是我测试的小程序代码:
*/

 #include "stdio.h"
#include "winsock.h"
#include "conio.h"

#pragma comment(lib,"ws2_32")

int prot=80;
int error=0;

char pagetext[40000]="/0"; //接收主机回应
char msg[0x30000];   //请求字符串

void httphead();   //填写HTTP协议-请求

int main()
{
 int iret;
 WSADATA wsa;
 SOCKET sock;
 struct sockaddr_in sin;

 httphead();  //写HTTP请求的函数

 if(WSAStartup(MAKEWORD(2,2),&wsa))
 {
  printf("WSAStartup Error:%d/n",WSAGetLastError());
  getche();
  return -1;
 }

 if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
 {
  printf("Socket Error:%d/n",WSAGetLastError());
  getche();
  return -1;
 }

 sin.sin_family=AF_INET;
 sin.sin_port=htons(8080);
 sin.sin_addr.s_addr=inet_addr("192.168.0.254");

 if(connect(sock,(struct sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR)
 {
  printf("Connect Error:%d/n",WSAGetLastError());
  printf("请检测网络连接!/n");
  getche();
  return -1;
 }

 if((iret=send(sock,msg,sizeof(msg),0))==SOCKET_ERROR)
 {
  printf("Send Error:%d/n",WSAGetLastError());
  getche();
  return -1;
 }

 while(true)
 {
  memset(pagetext,0,sizeof(pagetext));
  if((iret=recv(sock,pagetext,sizeof(pagetext),0))==SOCKET_ERROR)
  {
   printf("Recv Error:%d/n",WSAGetLastError());
   getche();
   return -1;
  }

  printf("%d/n",iret);
  printf("Re:/n");

  for(int i=0;i;)
  {
   printf("%c-",pagetext);
   printf("%d-",pagetext);

  }

  printf("%s",pagetext);
  printf("/n****************end*****************/n");

  if(pagetext[0]==0)
   break;
 }

 closesocket(sock);
 WSACleanup();

 getche();
 return 0;
}

void httphead()
{
 strcat(msg,"GET /php_info.php HTTP/1.1"); //----->GET /default.asp HTTP/1.1
 strcat(msg,"/r/n");

 strcat(msg,"Accept:*/*");
 strcat(msg,"/r/n");

 strcat(msg,"Accept-Language: zh-cn");
 strcat(msg,"/r/n");

 strcat(msg,"User-Agent: Mozilla/4.0(compatible;MSIE 5.01;Windows NT 5.0)");
 strcat(msg,"/r/n");

 strcat(msg,"Host:192.168.0.254"); //--------->
 strcat(msg,"/r/n");

 strcat(msg,"Connection:Keep-Alive");
 strcat(msg,"/r/n");
 strcat(msg,"/r/n");

 //printf();  //显示发送的头部
 //getchar();
}

原创粉丝点击