如果使用socket发送http请求(并且编译成可以被lr调用的压力测试脚本)

来源:互联网 发布:c网络编程技术教程 编辑:程序博客网 时间:2024/06/10 11:17
#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include <netdb.h> /*gethostbyname function */
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>


#include<openssl/rsa.h>
#include<openssl/pem.h>
#include<openssl/err.h>
#define OPENSSLKEY "/test.key"
#define PUBLICKEY "/test_pub.key"
#define BUFFSIZE 1024
#define MAXLINE 10240


char *my_encrypt(char *str,char *path_key){
    char *p_en;
    RSA *p_rsa;
    FILE *file;
    int flen,rsa_len;
    if((file=fopen(path_key,"r"))==NULL){
        perror("open key file error");
        return NULL;    
    }   
    if((p_rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL))==NULL){
    //if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL){   换成这句死活通不过,无论是否将公钥分离源文件
        ERR_print_errors_fp(stdout);
        return NULL;
    }   
    flen=strlen(str);
    rsa_len=RSA_size(p_rsa);
    p_en=(unsigned char *)malloc(rsa_len+1);
    memset(p_en,0,rsa_len+1);
    if(RSA_public_encrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_en,p_rsa,RSA_NO_PADDING)<0){
        return NULL;
    }   
    RSA_free(p_rsa);
    fclose(file);
    return p_en;
}
char *my_decrypt(char *str,char *path_key){
    char *p_de;
    RSA *p_rsa;
    FILE *file;
    int rsa_len;
    if((file=fopen(path_key,"r"))==NULL){
        perror("open key file error");
        return NULL;
    }
    if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
        ERR_print_errors_fp(stdout);
        return NULL;
    }
    rsa_len=RSA_size(p_rsa);
    p_de=(unsigned char *)malloc(rsa_len+1);
    memset(p_de,0,rsa_len+1);
    if(RSA_private_decrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_de,p_rsa,RSA_NO_PADDING)<0){
        return NULL;
    }
    RSA_free(p_rsa);
    fclose(file);
    return p_de;
}
EVP_PKEY * getKey(char * key_path) {
    X509 *cert = NULL;
    BIO *in = NULL;
    EVP_PKEY *key;


    in = BIO_new_file(key_path, "r");
    cert = PEM_read_bio_X509(in, NULL, NULL, NULL);
    if (cert != NULL) {
        key = (EVP_PKEY *) X509_get_pubkey(cert);
    } else {
        in = BIO_new_file(key_path, "r");
        key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
    }
    BIO_free(in);
    if (cert) {
        X509_free(cert);
    }
    return key;
}


char *my_encrypt2(unsigned char *str,int * plen){
    int cryptedlen;
    unsigned char *cryptedbuf;
    int i=0;
    EVP_PKEY *key;
    key = getKey(PUBLICKEY);

    *plen = EVP_PKEY_size(key);
    cryptedbuf = malloc((*plen) + 1);
    memset(cryptedbuf,0,(*plen)+ 1);


    if(RSA_public_encrypt(strlen(str),(unsigned char *)str,cryptedbuf,key->pkey.rsa,RSA_PKCS1_PADDING)<0){
       return NULL;
   }
    EVP_PKEY_free(key);
    for(i=0;i<128;i++) {
       printf(" %d ", (unsigned char)cryptedbuf[i]);
     }
      printf("\n");
    return cryptedbuf;
}
  


int opensocket(char *ip,int port)
{
  int connfd;
  char * servInetAddr = ip;
  int servPort = port;
  char dataBuffer[MAXLINE];
  struct sockaddr_in servaddr;
  //设置超时时间
  struct timeval timeout={30,0};//3s

  //connfd = socket(AF_INET, SOCK_STREAM, 0);
   if ((connfd=socket(AF_INET,SOCK_STREAM,0))== -1)
    {
        perror("socket");
        return 0;
    }


   if (setsockopt(connfd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&timeout,sizeof(timeout)) == -1)
    {
        perror("setsockopt");
       return 0;
    }


  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(servPort);
  inet_pton(AF_INET, servInetAddr, &servaddr.sin_addr);
 


  if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        perror("connect error");
        return -1;
   }


  else{
       //return 1;
       return connfd;
   }
}


void closesocket(int connfd){
close(connfd);
}

int  msgsend(int connfd,char *msg, int len){
char dataBuffer[MAXLINE];
bzero(dataBuffer,MAXLINE+1);
strncpy(dataBuffer,msg,strlen(msg));
int errSend = send(connfd,dataBuffer,len,0);
if(-1 == errSend)
      {
        return -1;
      }else{
return 1;
}
}


//对rsa加密后的数据进行发送
int rsa_msgsend(int connfd,char * source)
{
    char *ptr_en,*ptr_de;
    char send_msg[1024];
    int plen=0;
    ptr_en=my_encrypt2(source,&plen);
    char head[150];
    sprintf(head, "POST /auth HTTP/1.1\r\nHost: bjcm01.portal.freemse.360.cn\r\nAccept-Version: 1\r\nAppId:1\r\nUser-Agent:MSE 8.0.0;Android 5.0\r\nContent-Length: %d\r\n\r\n", plen);
    printf("plen :%d \n",plen);
   // printf("source is    :%s\n",start);
    //ptr_de=my_decrypt(ptr_en,OPENSSLKEY);
    //printf("jiemi data %s\n",ptr_de);
    //sprintf(send_msg,"%s%s",start,ptr_en);
    //printf("send_msg %s\n",start);
   int h_send_result = msgsend(connfd,head, strlen(head));
   printf("head: %s\n",head);
   int b_send_result =  msgsend(connfd,ptr_en, plen);
   printf("ptr_en: %s\n",ptr_en);
   if( h_send_result == -1 || b_send_result == -1){
    return -1;
   }
   else{
     return 1;
    }
}


//对比返回的结果
int cmprecvmsg(int connfd,char *msg,int len){
        char dataBuffer[MAXLINE];
        bzero(dataBuffer,MAXLINE+1);
        int recv_bytes = recv(connfd,dataBuffer,MAXLINE,0);
        //return dataBuffer;        
        if(recv_bytes < 0)
        {
             return -2;
        }


        if(memcmp(dataBuffer,msg,len)==0){
                return 1;
        }else{
                return -1;
        }

}



int gettimeofday(struct timeval *tv, struct timezone *tz);
int httpSendAndRcv(int sockfd,char *realhost){
         struct timeval t_start,t_end;
         long cost_time = 0;
         #define BUFSIZE 1024
        int ret, i,j, h;
        struct sockaddr_in servaddr;
        char str1[4096], str2[4096], buf[BUFSIZE];
        socklen_t len;
        fd_set   t_set1;
        struct timeval timeout={5,0}; //select等待5秒,5秒轮询,要非阻塞就置0 


        //发送数据
        memset(str1, 0, 4096);//一定要初始化一下该内存,因为在测试时发现发送的字符串有一些脏数据

        strcat(str1, "GET / HTTP/1.1\n");
        strcat(str1, "Host: test.com\r\n");
        strcat(str1, "RealHost:");
        strcat(str1, realhost);
        strcat(str1, "\r\n");
        strcat(str1, "Content-Type: application/x-www-form-urlencoded");
        strcat(str1, "\r\n\r\n");
        printf("%s\n",str1);
                
         gettimeofday(&t_start, NULL);
 
         long start = ((long)t_start.tv_sec)*1000+(long)t_start.tv_usec/1000;//为了获取毫秒的时间,只有将秒和微妙都转成毫秒来计算了
         printf("Start time: %ld ms\n", start);
               ret = write(sockfd,str1,strlen(str1));


               if (ret < 0) {
                    printf("发送失败!错误代码是%d,错误信息是'%s'\n",errno, strerror(errno));
                    exit(0);
                }else{
                    printf("消息发送成功,共发送了%d个字节!\n\n", ret);
                }
                while(1){
                   //sleep(1);
                   FD_ZERO(&t_set1);
                   FD_SET(sockfd, &t_set1);
                   h= 0;
                  // printf("--------------->1");
                   h= select(sockfd +1, &t_set1, NULL, NULL, &timeout);
                   //printf("--------------->2");

                   if (h == 0) break;  //如果在超时时间内没有数据返回认为http的response接受完毕,可以进行下一轮请求
                   if (h < 0) {
                        close(sockfd);
                        printf("在读取数据报文时SELECT检测到异常,该异常导致线程终止!\n");
                        return -1;
                };

                if (h > 0){
                        memset(buf, 0, 4096);
                        i= read(sockfd, buf, 4095);
                        if (i==0){
                                close(sockfd);
                                printf("读取数据报文时发现远端关闭,该线程终止!\n");
                                return -1;
                        }
                          // printf("recive");
                          printf("%s\n", buf);
                }
           }
       
       //获取结束时间
       gettimeofday(&t_end, NULL);
       long end = ((long)t_end.tv_sec)*1000+(long)t_end.tv_usec/1000;
       printf("End time: %ld ms\n", end);
       //统计网页响应的时间差(当然包括了一次超时时间)
       cost_time = end - start;
       printf("Cost time: %ld ms\n", cost_time);
       
       return 0;
}


//测试用
int main()
{
    //unsigned char *source="{\"phone\":\"10002415407\", \"token\":\"47\", \"wid\":\"1\"}";
     char *source="{\"phone\":\"1212121212\", \"token\":\"121212121\", \"wid\":\"wid\"}";
    //char *ptr_en,*ptr_de;
    char *ip="127.0.0.1";
    int port=80
    int connfd;
    char buf[20]; 
    char buf1[5]; 
    char * realhost="m.so.com";
    // char send_msg[1024];
    char dataBuffer[21700];
    int j;
    //int plen=0;
    //ptr_en=my_encrypt2(source,&plen);
    //char start[150];
    //sprintf(start, "POST /auth HTTP/1.1\r\nHost: bjcm01.portal.freemse.360.cn\r\nAccept-Version: 1\r\nUser-Agent:MSE 8.0.0;Android 5.0\r\nContent-Length: %d\r\n\r\n", plen);
    //printf("plen :%d \n",plen);
   // printf("source is    :%s\n",start);
    //ptr_de=my_decrypt(ptr_en,OPENSSLKEY);
    //printf("jiemi data %s\n",ptr_de);
    connfd=opensocket(ip,port);
    //sprintf(send_msg,"%s%s",start,ptr_en);
    //printf("send_msg %s\n",start);
   // msgsend(connfd,start, strlen(start));
    //msgsend(connfd,ptr_en, plen);
    rsa_msgsend(connfd,source);
    recv(connfd,dataBuffer,21700,0);
    sscanf(dataBuffer, "%*[^\"]%[^m]", buf); 
    sscanf(buf, "%*[^:]:%[^,]", buf1); 
    printf("recv %s\n",dataBuffer);
    printf("%s\n",buf1);
    for (j=0;j<3;j++) msgrecv(connfd,realhost);
    closesocket(connfd);
    return 0;
}
1 0