自己动手学TCP/IP–http协议(http报文头)

在前面的一篇文章中,简单了介绍了HTTP报文格式,详情参考http://www.firefoxbug.net/?cat=47

这里大概介绍下基本的,常见的HTTP包头格式。

POST /report/getComment.jsp HTTP/1.1
Host: yeeg.com
Connection: keep-alive
Content-Length: 161
Origin: http://www.1g1g.com
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7
content-type: application/x-www-form-urlencoded
Accept: */*
Referer: http://www.1g1g.com/player/loader.swf?uid=0.8106261373031884
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=C3F105F72E3602D6292D3E4561E8E400

上面是一个POST包的包头,其中Content-Length字段里面的值就是POST包数据段的长度。可以用

wireshark抓取POST包,会发现,post包是把报文头和数据内容分开来发的,会被TCP分片,然后重组。

具体这里不详细讨论。

GET /enclosure/2010-09-10T02_51_05-07_00.mp3 HTTP/1.1
Host: 805665086.podomatic.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7
Accept: */*
Referer: http://www.1g1g.com/player/loader.swf?uid=0.8106261373031884
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

上面是一个GET包,GET包请求的资源都是在URL里面的,所以数据段也就没有了,可以通过抓包分析。

HTTP/1.1 200 OK
Date: Tue, 10 Jul 2012 09:12:52 GMT
Server: Apache/2.2.14 (Ubuntu)
Last-Modified: Thu, 23 Dec 2010 19:29:26 GMT
ETag: "960fcf-4a6459-49818e3486374"
Accept-Ranges: bytes
Content-Length: 487
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: audio/mpeg

上面是一个http响应包,Content-Length指明了数据段的大小。

下面是我今天用C写了解析HTTP报文头的程序。注意:下面代码只主要用libcap实现实现了部分功能,具体

是解析GET包头,POST包头,还有HTTP相应包头,可能存在一些不足,希望大家多多交流。

  1. /* 
  2.     capture http packet by firefoxbug 
  3. */  
  4. #include <pcap.h>  
  5. #include <stdio.h>  
  6. #include <stdlib.h>                 
  7. #include <string.h>  
  8. #include <sys/socket.h>  
  9. #include <arpa/inet.h>          
  10. #include <net/ethernet.h>  
  11. #include <netinet/ip_icmp.h>  //Provides declarations for icmp header  
  12. #include <netinet/udp.h>      //Provides declarations for udp header  
  13. #include <netinet/tcp.h>      //Provides declarations for tcp header  
  14. #include <netinet/ip.h>       //Provides declarations for ip header  
  15.   
  16. #define BUFFSIZE 1500  
  17.   
  18. typedef struct port{  
  19.     unsigned int src_port;  
  20.     unsigned int des_port;  
  21. }Port;  
  22.   
  23. Port port;  
  24. int tcp=0;  
  25. FILE *logfile;  
  26. int size;  
  27.   
  28. void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer);  
  29. char *print_tcp_packet(const char *Buffer);  
  30. void get_line(char *data,char *buff,int length);  
  31. void print_http_req_packet(char *data);  
  32. void print_http_ans_packet(char *data);  
  33.   
  34. int main(int argc,char *argv[])  
  35. {  
  36.     pcap_if_t *alldevsp , *device;  
  37.     pcap_t *handle; //Handle of the device that shall be sniffed  
  38.   
  39.     char errbuf[100] , *devname , devs[100][100];  
  40.     int count = 1 , n;  
  41.   
  42.     //First get the list of available devices  
  43.     printf("Finding available devices ... ");  
  44.     if( pcap_findalldevs( &alldevsp , errbuf) )  
  45.     {  
  46.         printf("Error finding devices : %s" , errbuf);  
  47.         exit(1);  
  48.     }  
  49.     printf("Done");  
  50.   
  51.     //Print the available devices  
  52.     printf("\nAvailable Devices are :\n");  
  53.     for(device = alldevsp ; device != NULL ; device = device->next)  
  54.     {  
  55.         printf("%d. %s - %s\n" , count , device->name , device->description);  
  56.         if(device->name != NULL)  
  57.         {  
  58.             strcpy(devs[count] , device->name);  
  59.         }  
  60.         count++;  
  61.     }  
  62.   
  63.     //Ask user which device to sniff  
  64.     printf("Enter the number of the device you want to sniff : ");  
  65.     scanf("%d" , &n);  
  66.     devname = devs[n];  
  67.   
  68.     //Open the device for sniffing  
  69.     printf("Opening device %s for sniffing ... " , devname);  
  70.     handle = pcap_open_live(devname , 65536 , 1 , 0 , errbuf);  
  71.   
  72.     if (handle == NULL)  
  73.     {  
  74.         fprintf(stderr, "Couldn't open device %s : %s\n" , devname , errbuf);  
  75.         exit(1);  
  76.     }  
  77.     printf("Done\n");  
  78.   
  79.     logfile=fopen("log.txt","w");  
  80.     if(logfile==NULL)  
  81.     {  
  82.         printf("Unable to create file.");  
  83.     }  
  84.   
  85.     //Put the device in sniff loop  
  86.     pcap_loop(handle , -1 , process_packet , NULL);  
  87.   
  88.     return 0;  
  89. }  
  90.   
  91. void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer)  
  92. {  
  93.     size = header->len;  
  94. //  fprintf(logfile,"length of packet : %d \n",size);     
  95.     //Get the IP Header part of this packet , excluding the ethernet header  
  96.     struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));  
  97.     switch (iph->protocol) //Check the Protocol and do accordingly...  
  98.     {  
  99.   
  100.         case 6:  //TCP Protocol  
  101.             ++tcp;    
  102.         //  printf("TCP : %d \n", tcp);  
  103.             unsigned char *data = print_tcp_packet(buffer);   
  104.             if (size <= 0)  
  105.                 break;  
  106.             if (port.des_port == 80)              
  107.             {  
  108.                 print_http_req_packet(data);  
  109.             }  
  110.             else if ( port.src_port == 80 )  
  111.             {  
  112.                 print_http_ans_packet(data);  
  113.             }  
  114.             break;  
  115.     }  
  116.   
  117. }  
  118.   
  119. char *print_tcp_packet(const char *Buffer)  
  120. {  
  121.     //IP header  
  122.     struct iphdr *iph = (struct iphdr *)( Buffer  + sizeof(struct ethhdr) );  
  123.     unsigned int iphdrlen = iph->ihl*4;  
  124.     //TCP header  
  125.     struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr));  
  126.       
  127.     port.src_port = ntohs(tcph->source);  
  128.     port.des_port = ntohs(tcph->dest);  
  129.   
  130.     // mac_header + ip_header + tcp_header  
  131.     int header_size =  sizeof(struct ethhdr) + iphdrlen + tcph->doff*4;  
  132.     size = size - header_size;   
  133. //  fprintf(logfile,"length of header : %d \n",header_size );  
  134.     return (char *)(Buffer + header_size);  
  135. }  
  136.   
  137. void print_http_req_packet(char *data)  
  138. {     
  139.     if( strncmp(data,"GET",3) == 0 || strncmp(data,"POST",4) == 0 )   
  140.     {  
  141.         fprintf(logfile,"\n/***********************length of data : %d**********************/ \n",size);  
  142.         fprintf(logfile,"From %d To %d \n",port.src_port,port.des_port);  
  143.         int i = 0;    
  144.         for( ; i < size ; ++i)  
  145.         {  
  146.             fprintf(logfile,"%c",*(data + i));  
  147.         }  
  148.         fprintf(logfile,"/***************************** end *******************************/ \n\n");  
  149.     }  
  150.     return ;  
  151. }  
  152.   
  153. void print_http_ans_packet(char *data)  
  154. {  
  155.     if( strncmp(data,"HTTP",4) == 0 )   
  156.     {  
  157.         fprintf(logfile,"\n/***********************length of data : %d**********************/ \n",size);  
  158.         fprintf(logfile,"From %d To %d \n",port.src_port,port.des_port);  
  159.         char buff[BUFFSIZE] = {'\0'};  
  160.         get_line(data,buff,size);  
  161.         fprintf(logfile,"%s",buff);  
  162.         unsigned int off = strlen(buff);  
  163.         size = size - off;  
  164.         while(strcmp(buff,"\r\n") != 0)  
  165.         {  
  166.             memset(buff,'\0',sizeof(buff));  
  167.             get_line(data + off,buff,size);  
  168.             fprintf(logfile,"%s",buff);  
  169.             off = off + strlen(buff);  
  170.             size = size - off;  
  171.         }  
  172.         fprintf(logfile,"/***************************** end *******************************/ \n\n");  
  173.     }  
  174. }  
  175.   
  176. void get_line(char *data,char *buff,int length)  
  177. {  
  178.     int i = 0;  
  179.     char ch;  
  180.     for ( ; i < length;++i)  
  181.     {  
  182.         ch = *(data + i);  
  183.         *(buff + i) = ch;  
  184.         if(ch == '\n')  
  185.             break;  
  186.     }  
  187. }  
上一篇:.NET 二维码生成(ThoughtWorks.QRCode)


下一篇:如何把.cs文件编译成DLL文件