Chinaunix首页 | 论坛 | 博客
  • 博客访问: 444482
  • 博文数量: 403
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: -70
  • 用 户 组: 普通用户
  • 注册时间: 2016-09-05 12:45
文章分类

全部博文(403)

文章存档

2014年(3)

2013年(1)

2012年(3)

2011年(21)

2010年(13)

2009年(64)

2008年(9)

2007年(36)

2006年(253)

分类: 系统运维

2006-08-02 21:03:06

/*
对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请求,访问命令:[url][/url]

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请求,访问命令:[url][/url]

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协议里面还有我没有发现的东西,但基本的东西我想我这里面写应该差不多了!

下面是我测试的小程序代码:
*/
//write by Gxter
//blog   gxter.bokee.com

#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.119");


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[i]);
  printf("%d-",pagetext[i]);
  //if(i==9)
  // printf("\n");
}
*/
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.119");  //------->
strcat(msg,"\r\n");

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

//printf("%s",msg);//显示发送的头部
//getchar();
}
阅读(9274) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~