[Socket]HTTP报文提交工具

作者在 2008-01-09 20:33:45 发布以下内容

以前曾用VB6.0写过一个灌水工具,用了WinSock控件。不过我还是喜欢命令行的工具。最近正学习套接字,于是就用C重写了这个工具。功能比以前那个更大。用来学习HTTP协议或者用来灌水都是相当不错的(呵呵,别骂我...)

先发个截图

关于程序的使用方法,帮助里面有。按照老样子,开源:

//HTTP报文提交工具 By RedIce
//E-mail:redice@see.xidian.edu.cn
//http://redice.1.suhai.com.cn
#include <winsock2.h> //Winsock API头文件
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib") //Winsock API连接库文件
char http_data[6000];//http报文缓冲区
char recvbuf[200];//接收缓冲区
void usage();//函数声明-程序使用说明
void main(int argc,char *argv[])
{
 char *ICMP_DEST_IP;//目标主机IP
 FILE * fileopr;
 WSADATA wsaData;
 SOCKET sender;
 char thecurrentpath[200];//当前程序所在的路径
 struct sockaddr_in dest;
 PHOSTENT hostinfo;//主机信息(域名->IP)
 int n=1; //发送数据包次数
 int i;
 int ret;
 int timeout=2000;//超时
 int filesize;//HTTP报文文件大小
 char httpfile[200];//HTTP报文所在的文件
 int getreturn=1;/*是否回显服务器返回的数据
       false表示不显示,true表示显示
       当n>1时,getreturn强制为false
       */ 
 //命令行参数处理
 memset(httpfile,0,200);
 if(1==argc)//如果只有默认的命令行参数 则给出程序说明 并退出程序
 {
  usage();
  return;
 }
 else//如果有多个参数
 {
  for(i=1;i<=argc-1;i++)
  {
   if(strstr(argv[i],"-r"))
   {
    getreturn=1;
   }
   if(strstr(argv[i],"-t"))
   {
    n=atoi(argv[i+1]);
    if(n<0)
    {
     printf("-n 参数必须大于0\n");
     return;
    }
    i++;
   }
   if(strstr(argv[i],"-f"))
   {
      if(strlen(argv[i+1])>=200)
      {
       printf("指定的文件名太长!\n");
       return;
      }
      strcpy(httpfile,argv[i+1]);
      i++;
   }
   if(strstr(argv[i],"-?"))
   {
    usage();
    return;
   }
  }
 }

 ICMP_DEST_IP=argv[argc-1];//取得域名(IP)
 if(n>1)//如果-n参数大于1则不回显服务器返回的数据
 {
  getreturn=0;
 }
 //如果用户指定了http报文路径则读取文件中的内容,否则使用默认报文
 memset(http_data,0,6000);
 if(strlen(httpfile))
 {
  if(!strstr(httpfile,"\\"))//如果是当前路径
  {
   memset(thecurrentpath,0,200);
   for(i=strlen(argv[0])-1;i>=0;i--)
   {
    if(*(argv[0]+i)=='\\') break;//如果找到'\则跳出'
   }
   memcpy(thecurrentpath,argv[0],i+1);
   //判断当前路径最后一个字符是否为'\'
   if(thecurrentpath[strlen(thecurrentpath)-1]!='\\')
   {
    thecurrentpath[strlen(thecurrentpath)]='\\';
   }
   strcat(thecurrentpath,httpfile);
   memset(httpfile,0,200);
   strcpy(httpfile,thecurrentpath);
  }
  //读取文件中的报文
  fileopr=fopen(httpfile,"r");//以只读的方式打开文件
  if(NULL==fileopr)
  {
   printf("打开文件失败,请检查文件的路径是否正确!%s\n",httpfile);
   return;
  }
  //取得文件大小
  if(fseek(fileopr,0,SEEK_END))
  {
   printf("计算文件大小失败!\n");
   return;
  }
  filesize=ftell(fileopr);
  if(filesize<=0||filesize>6000)
  {
   printf("文件大小有误(不能为空且不能大于6000Bytes)!\n");
   return;
  }
  if(fseek(fileopr,0,SEEK_SET))
  {
   printf("计算文件大小失败!\n");
   return;
  }
  if(!fread(http_data,sizeof(char),6000,fileopr))
  {
   printf("读取HTTP报文文件失败!\n");
   return;
  }
  fclose(fileopr);//关闭打开的文件
 }
 else
 {
  //默认的报文
     //GET / HTTP/1.1
        //Accept: */*
  //Accept-Language: zh-cn
  //Host: 你输入的域名(IP地址)
  //Connection: Keep-Alive
  strcpy(http_data,"GET / HTTP/1.1\nAccept: */*\nAccept-Language: zh-cn\nHost: ");
  strcat(http_data,ICMP_DEST_IP);
  strcat(http_data,"\nConnection: Keep-Alive\n\n");
 }
   //套接字版本协商
   if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
   {
    printf("初始化套接字失败!\n");
    return;
   }

 //域名解析
 hostinfo=gethostbyname(ICMP_DEST_IP); //参数为需要解析的主机名
 if(NULL==hostinfo)
 {
  printf("无法解析主机%s的IP地址!",ICMP_DEST_IP);
  WSACleanup();
  return;
 }
 else
 {
  ICMP_DEST_IP=inet_ntoa(*(struct in_addr*)*hostinfo->h_addr_list);
 }

   //创建流式套接字
   sender=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   if(INVALID_SOCKET==sender)
   {
    printf("创建套接字失败!\n");
    WSACleanup();
    return;
   }
   //设置接收超时
   if(SOCKET_ERROR ==setsockopt(sender,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)))
 {
  printf("设置套接字超时失败!\n");
  closesocket(sender);
  WSACleanup();
  return;
 }
   //填充目的地址结构体
 dest.sin_family=AF_INET;
 dest.sin_addr.S_un.S_addr =inet_addr(ICMP_DEST_IP);
 dest.sin_port=htons(80);
 if(SOCKET_ERROR==connect(sender,(SOCKADDR *) &dest,sizeof(dest))) 
 {
  printf("连接目的主机失败!\n");
  closesocket(sender);
  WSACleanup();
     return;
 }
 printf("提交报文:\n%s\n",http_data);
 for(i=1;i<=n;i++)
 {
  if(SOCKET_ERROR==send(sender,http_data,strlen(http_data),0))
  {
   printf("发送数据出错!\n");
   closesocket(sender);
   WSACleanup();
   return;
  }
  else
  {
   printf("已提交报文%d次\n",i);
  }
 }
 if(getreturn)//接收服务器发送的数据
 { 
  printf("\n服务器返回的报文:\n%s\n",recvbuf);
  while(1)//循环接收数据
  { memset(recvbuf,0,200);
   ret=recv(sender,recvbuf,200,0);
   if(-1==ret)
    break;//返回-1表示接收完毕
   else
   {
    printf("%s",recvbuf);
   }
  }
 }
 printf("\n");
 //关闭套接字
 closesocket(sender);
 WSACleanup();
 return;
}

//程序使用说明
void usage()
{
 printf("HTTP报文提交工具\n\n");
 printf("By RedIce\n");
 printf("E-mail:redice@see.xidian.edu.cn\n");
 printf("http:\\redice.1.suhai.com.cn\n");
 printf("Usage: SendHttp.exe [-n] [-r] [-f] 目的主机(域名/IP地址)\n");
 printf("Options:\n\n");
 printf("        -n 指定发送报文的次数,这个参数用来灌水很不错\n");
 printf("        -r 如果有该参数 程序将显示服务器返回的报文信息\n"); 
 printf("           注意:如果-n参数指定的值大于1,-r将被忽略\n");
 printf("        -f 指定HTTP数据包文所在的文件\n");
 printf("           注意:如果不指定该参数,程序将使用默认报文:GET / HTTP/1.1\n");
 printf("        -? 显示该帮助信息\n\n");
}

默认分类 | 阅读 3315 次
文章评论,共0条
游客请输入验证码
浏览585894次