#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;
}