您的位置:首页 > 理论基础 > 计算机网络

c实现的iOS http下载类。支持自己设定http 头(比如cookie等)

2014-10-21 16:45 465 查看
也许有人要问为什么要自己用c写?

原因是:

1 我是菜鸟

2 我最最初选择了AsyncSocket,弄了很久,基本上稳定了,但有时候出现了数据不完整,但我又没办法在这个时候识别到并重试;所以不完美,最后放弃

3 我又用NSMutableURLRequest+NSURLConnection,这个玩意儿能帮你处理不定长度的返回内容,但有2个问题:a、修改Connection为closed无效,Accept、Accept-Language头删除不了;b、某些页面浏览器能正常打开,但NSURLConnection却只能获得http头,获取不了内容,这听起来不可能,但我试过了同步sendSynchronousRequest、异步委托“connectionWithRequest:request delegate:self”、异步队列“NSURLConnection
sendAsynchronousRequest:request queue:queue completionHandler”,统统不行。我实在不知道错在哪里。

最后我只能上了我的绝招,逼不得已,用了c来实现。

上代码,造福百姓:

#include <stdio.h>
//#include <malloc.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <math.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <stdarg.h>
#include <strings.h>

#ifndef HELPER
//#define DEBUG 1//定义了就会显示很多信息
#define HELPER 1

typedef struct {
//char shecma[8];
char host[128];
char url[1024];
int port;
//char queryString[1024];
} URI;
//flag=1会替换#和?,返回的是新申请的内存空间(实际上是replace函数申请的)
char *encodeURI(char *data, int flag);
long microTime();
//找出url的主机和url地址(域名后的部分)及端口
URI parseUrl(char * url);
//截取字符串
char* substr(char* str, int start, int len);
//转小写
void strToLower(char * str);
//转大写
void strToUpper(char * str);
//分割字符串
char** split(char *strin, char *seprator, int *l, int max);
//查找字符位置
unsigned long strpos(char *str, char *find);
//替换,返回的需要释放,至多替换150个
char* replace(char *strin, char *find, char *replace);
char* replaceAndCount(char *strin, char *find, char *replace, int *count);
//替换,至多替换150个,与replace的区别在于,此函数会把你传进去的原字符串free掉
char* doReplace(char *strin, char *find, char *replace);
//传入字符获取字符代表的今天的毫秒
long date(const char *ft);

//现在的毫秒
long Time();
//去除头尾的空白
char *trim(char *str);
//读文件
char* readFile(char* filename, int limit);
//写文件
void fastWriteFile(char* filename, char* data, int append);
void writeFile(char* filename, char* data, unsigned long len, int append);
char* getUniqueString();
int myrand();
int getRand(int min, int max);
//能保证dest以0结尾,注意,不能处理内存越界,dest可用内存至少为len+1
void sstrncpy(char* dest, char* src, unsigned long len);
char* make_message(const char *fmt, ...);
void dateStr(const char *ft, char* rtn);
void dateStrByTs(const char *ft, char* rtn, long ts);
void dateStrByDiffSecondsOfToday(const char *ft, char* rtn, long ts);
int isLower(char c);
int isUpper(char c);
int toLower(char c);
int toUpper(char c);
unsigned long parse16(char* str);
#endif


#include "helper.h"

void n2fs(long i, char *buf) {
long G = 1024 * 1024 * 1024;
long M = 1024 * 1024;
long K = 1024;
//char *buf=malloc(128);//[128];
memset(buf, 0, 128);
int j = 0;
/*if(i>T)
{
j=floor(i/T);
sprintf(buf,"%d T",j);
i=i%T;
}*/
if (i > G) {
j = floor(i / G);
if (strlen(buf) > 0)
sprintf(buf, "%s,%dG", buf, j);
else
sprintf(buf, "%dG", j);
i = i % G;
}
if (i > M) {
j = floor(i / M);
if (strlen(buf) > 0)
sprintf(buf, "%s,%dM", buf, j);
else
sprintf(buf, "%dM", j);
i = i % M;
}
if (i > K) {
j = floor(i / K);
if (strlen(buf) > 0)
sprintf(buf, "%s,%dK", buf, j);
else
sprintf(buf, "%dK", j);
i = i % K;
}
if (i > 0) {
if (strlen(buf) > 0)
sprintf(buf, "%s,%ldByte", buf, i);
else
sprintf(buf, "%ldByte", i);
}
}

long date(const char *ft) {
int i = 0;
struct tm *local;
time_t t;
t = time(NULL);
local = localtime(&t);
double j = 0;

while (i < strlen(ft)) {
switch (ft[i]) {
case 'Y':
j = j + (local->tm_year + 1900) * 10000000000.;
break;
case 'm':
j = j + (local->tm_mon + 1) * 100000000.;
break;
case 'd':
j = j + local->tm_mday * 1000000.;
break;
case 'H':
j = j + local->tm_hour * 10000;
break;
case 'i':
j = j + local->tm_min * 100;
break;
case 's':
j = j + local->tm_sec;
break;
}

i++;
}
return j;
}
/**
* 获得今天制定格式的
*/
void dateStr(const char *ft, char* rtn) {
return dateStrByTs(ft, rtn, 0);
}
void dateStrByDiffSecondsOfToday(const char *ft, char* rtn, long ts) {
time_t t;
t = time(NULL);
long in = ((long) t) + ts;
//printf("T=%ld, ts=%ld, in=%ld\n", (long) t, ts, in);
return dateStrByTs(ft, rtn, in);
}
void dateStrByTs(const char *ft, char* rtn, long ts) {
int i = 0;
struct tm *local;
time_t t;

if (ts == 0)
t = time(NULL);
else
t = (time_t) ts;

local = localtime(&t);
int j = 0;

rtn[0] = 0;
while (i < strlen(ft)) {
switch (ft[i]) {
case 'Y':
j = (local->tm_year + 1900);
sprintf(rtn, "%s%d", rtn, j);
break;
case 'y':
j = (local->tm_year + 1900);
j -= (int) (j / 100);
sprintf(rtn, "%s%d", rtn, j);
break;
case 'm':
j = (local->tm_mon + 1);
sprintf(rtn, j < 10 ? "%s0%d" : "%s%d", rtn, j);
break;
case 'n':
j = (local->tm_mon + 1);
sprintf(rtn, "%s%d", rtn, j);
break;
case 'd':
j = local->tm_mday;
sprintf(rtn, j < 10 ? "%s0%d" : "%s%d", rtn, j);
break;
case 'D':
j = local->tm_mday;
sprintf(rtn, "%s%d", rtn, j);
break;
case 'j':
j = local->tm_mday;
sprintf(rtn, "%s%d", rtn, j);
break;
case 'N':
j = local->tm_wday;
sprintf(rtn, "%s%d", rtn, j);
break;
case 'H':
j = local->tm_hour;
sprintf(rtn, j < 10 ? "%s0%d" : "%s%d", rtn, j);
break;
case 'G':
j = local->tm_hour;
sprintf(rtn, "%s%d", rtn, j);
break;
case 'i':
j = local->tm_min;
sprintf(rtn, j < 10 ? "%s0%d" : "%s%d", rtn, j);
break;
case 'I':
j = local->tm_min;
sprintf(rtn, "%s%d", rtn, j);
break;
case 's':
j = local->tm_sec;
sprintf(rtn, j < 10 ? "%s0%d" : "%s%d", rtn, j);
break;
case 'S':
j = local->tm_sec;
sprintf(rtn, "%s%d", rtn, j);
break;
default:
sprintf(rtn, "%s%c", rtn, ft[i]);
break;
}

i++;
}
}
char** split(char *strin, char *seprator, int *l, int max) {
char **rtn;
rtn = (char **) malloc(sizeof(char **));
char *str = strdup(strin);
char *str0 = str;
char *p;

p = strstr(str, seprator);
if (p == NULL) {
*l = 1;
*rtn = str;
return rtn;
}

unsigned long len, spl, inlen, plen;
spl = strlen(seprator);
max--;
*l = 0;
while (p != NULL) {
if (*l > 0)
rtn = realloc(rtn, ((*l) + 1) * sizeof(char **));
inlen = strlen(str);
plen = strlen(p);
if (!plen)
break;
len = inlen - plen;

rtn[*l] = malloc(len + 1);
strncpy(rtn[*l], str, len);
rtn[*l][len] = 0;

str += (len + spl);
p = strstr(str, seprator);

(*l)++;
if (*l == max || p == NULL) {
/*if (*l == max) {
len = strlen(rtn[*l - 1]) + strlen(str) + 1;
rtn[*l - 1] = realloc(rtn[*l - 1], len);
strncat(rtn[*l - 1], str, len - 1);
} else {*/
len = strlen(str);
rtn = realloc(rtn, ((*l) + 1) * sizeof(char **));
rtn[*l] = malloc(len + 1);
strncpy(rtn[*l], str, len);
rtn[*l][len] = 0;
//}
(*l)++;
break;
}
}
free(str0);
return rtn;
}
unsigned long strpos(char *strin, char *seprator) {
char *right = strstr(strin, seprator);
if (right == NULL)
return -1;

return strlen(strin) - strlen(right);
}
char* doReplace(char *strin, char *find, char *replace) {
//int len = strlen(strin);
int count = 0;
char *rtn = replaceAndCount(strin, find, replace, &count);
//strcpy(strin, rtn);
free(strin);
return rtn;
}
char* replace(char *strin, char *find, char *replace) {
int count = 0;
return replaceAndCount(strin, find, replace, &count);
}
char* replaceAndCount(char *strin, char *find, char *replace, int *count) {
char* rtn;
unsigned long lenf = strlen(find);
unsigned long lenr = strlen(replace);
unsigned long rtn_len;

if (lenf > lenr)
rtn_len = strlen(strin) + 1;
else
rtn_len = strlen(strin) + (lenr - lenf) * 1000 + 1;

rtn = (char*) malloc(rtn_len);
rtn[0] = 0;
char *str = strdup(strin);
char *sp = strdup(find);
char *p;

p = strstr(str, sp);
if (p == NULL) {
free(sp);
free(rtn);
return str;
}
unsigned long spl = strlen(sp);
unsigned long sl = strlen(str);
unsigned long i = 0, len;

char *tmp = (char*) malloc(sl + 1);
while (p != NULL) {
if (i++ > 0)
strcat(rtn, replace);
len = sl - strlen(p);
strncat(rtn, str, len);
strcpy(tmp, p + spl);
strcpy(str, tmp);
sl = strlen(str);
p = strstr(str, sp);
(*count)++;
if (*count >= 999)
break;
}

if (strlen(str)) {
if (i > 0)
strcat(rtn, replace);
strcat(rtn, str);
(*count)++;
}

free(tmp);
free(str);
free(sp);
return rtn;
}

long microTime() {
struct timeval start;
//struct timezone tz; //后面有说明
gettimeofday(&start, NULL); //gettimeofday(&start,&tz);结果一样
//	printf("start.tv_sec:%d\n",start.tv_sec);
//	printf("start.tv_usec:%d\n",start.tv_usec);

return start.tv_sec * 1000 + start.tv_usec / 1000;
}

long Time() {
time_t t;
t = time(NULL);
return (long) t;
}

char *trim(char *str) {
int i = 0;
unsigned long l = 0;
char *s; //=malloc(strlen(str)+1);
s = strdup(str);
while (*(s + i) == 13 || *(s + i) == 10 || *(s + i) == 32) {
i++;
}
memset(s, 0, strlen(s));
strcpy(s, str + i);
l = strlen(s) - 1;
while (*(s + l) == 13 || *(s + l) == 10 || *(s + l) == 32) {
l--;
}
memset(s, 0, strlen(s));
strncpy(s, str + i, l + 1);
return s;
}
char* readFile(char* filename, int limit) {
char *buffer = malloc(limit + 1);
buffer[0] = 0;
FILE *fp;

if ((fp = fopen(filename, "r")) == 0) {
free(buffer);
buffer = NULL;
return NULL;
}

rewind(fp);
int pos = 0;
int len = 10;
unsigned long l;

char* buf = malloc(len);
while (!feof(fp)) {
l = fread(buf, 1, len, fp);
pos += l;
if (l > 0)
strncat(buffer, buf, l);

if (pos + len > limit) {
printf("filesize %s bigger than %d\n", filename, limit);
break;
}
}
free(buf);
//printf("Read %s, data length: %d\n", filename, pos);
fclose(fp);
buffer[pos - 1] = '\0';
return buffer;
}
void fastWriteFile(char* filename, char* data, int append) {
writeFile(filename, data, strlen(data), append);
}
void writeFile(char* filename, char* data, unsigned long len, int append) {
FILE *fp;

if ((fp = fopen(filename, append > 0 ? "a+" : "w+")) == 0) {
return;
}

fwrite(data, len, 1, fp);
fclose(fp);
}
void strToLower(char * str) {
unsigned long i, len;
len = strlen(str);
for (i = 0; i < len; i++)
if (isUpper(str[i]))
str[i] = toLower(str[i]);
}
void strToUpper(char * str) {
unsigned long i, len;
len = strlen(str);
for (i = 0; i < len; i++)
if (isLower(str[i]))
str[i] = toUpper(str[i]);
}
int toLower(char c){
return c+32;
}
int toUpper(char c){
return c-32;
}
int isLower(char c){
return c>=97&&c<=122?1:0;
}
int isUpper(char c){
return c>=65&&c<=90?1:0;
}
char* substr(char* str, int start, int len) {
char* rtn = malloc(len + 1);
rtn[len] = 0;
memcpy(rtn, str + start, len);
return rtn;
}
/**
* 最多替换1000个替换项
*/
char *encodeURI(char *data, int flag) {
char* tmp = (char*) malloc(strlen(data) + 1);
strcpy(tmp, data);
tmp = doReplace(tmp, "%", "%25");
tmp = doReplace(tmp, " ", "%20");
tmp = doReplace(tmp, "	", "%09");
tmp = doReplace(tmp, "\"", "%22");
if (flag) {
tmp = doReplace(tmp, "#", "%23");
tmp = doReplace(tmp, "?", "%3F");
}
return tmp;
}
URI parseUrl(char * url) {
URI uri;
int len = strlen(url);
char* schema = substr(url, 0, 7);
strToLower(schema);
char* left = malloc(len + 1);
left[0] = 0;
if (strcmp(schema, "http://") == 0) {
len -= 7;
strncat(left, url + 7, len);
} else {
strcpy(left, url);
}

char *_uri = strchr(left, '/');

char *host;
char *pstr = NULL;

if (_uri == NULL) {
_uri = "/";
host = substr(left, 0, len);
} else {
host = substr(left, 0, len - strlen(_uri));
pstr = strchr(host, ':');
}

if (pstr != NULL) {
char* tmp = calloc(1, strlen(_uri));
strncpy(tmp, host, strlen(host) - strlen(pstr));
strcpy(host, tmp);
uri.port = atoi(pstr + 1);
free(tmp);
} else
uri.port = 80;

strcpy(uri.host, host);
strcpy(uri.url, _uri);
free(left);
free(schema);
free(host);
return uri;
}

char* getUniqueString() {
char *rtn = calloc(1, 128);
struct timeval start;
gettimeofday(&start, NULL);
pid_t tid;
tid = syscall(SYS_gettid);

sprintf(rtn, "%d_%ld_%d_%d", myrand(), start.tv_sec * 1000 + start.tv_usec,
getpid(), tid);
return rtn;
}
int srand_seed_set = 0;
int getRand(int min, int max) {
if (!srand_seed_set) {
srand_seed_set = 1;
time_t t;
srand((unsigned) time(&t));
}
if (max < min)
return min;

double m = 1.0 / (max - min + 1);
double d = ((double) rand()) / RAND_MAX;

return min + d / m;
}
int myrand() {
if (!srand_seed_set) {
srand_seed_set = 1;
time_t t;
srand((unsigned) time(&t));
}
return rand();
}
//能保证dest以0结尾,注意,不能处理内存越界,dest可用内存至少为len+1
void sstrncpy(char* dest, char* src, unsigned long len) {
unsigned long l = strlen(src);
unsigned long wl = l > len ? len : l;
strncpy(dest, src, wl);
dest[wl] = 0;
}

char *make_message(const char *fmt, ...) {
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p, *np;
va_list ap;

if ((p = malloc(size)) == NULL)
return NULL;

while (1) {
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
return p;
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else
/* glibc 2.0 */
size *= 2; /* twice the old size */
if ((np = realloc(p, size)) == NULL) {
free(p);
return NULL;
} else {
p = np;
}
}
return NULL;
}

unsigned long parse16(char* strIn) {
char* str = malloc(strlen(strIn)+1);
char* strO = str;
sstrncpy(str, strIn, strlen(strIn));

unsigned long var = 0;
unsigned long t;
//unsigned long len = strlen(str);

if (var > 8){ //最长8位
free(str);
return -1;
}
strToUpper(str); //统一大写
for (; *str; str++) {
if (*str >= 'A' && *str <= 'F')
t = *str - 55; //a-f之间的ascii与对应数值相差55如'A'为65,65-55即为A
else
t = *str - 48;
var <<= 4;
var |= t;
}
free(strO);
return var;
}

/*
int main(int argc, char **argv)
{
if(argc<4)
{
printf("Usage: %s strig str1 str2\n",argv[0]);
exit(1);
}

printf("pos=%d\n",strpos(argv[1],argv[2]));
printf("replaced=%s\n",replace(argv[1],argv[2],argv[3]));

int ll=3;
char **rtn=split(argv[1],argv[2],ll);

while(ll>0){
ll--;
printf("%s\n",*rtn);
**rtn++;
}
return 1;
}
*/


#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
//#include <malloc.h>
#include <strings.h>
#include <string.h>
#include "helper.h"

int openRequest(char *domain, int port, char *uri, char *rtn, char* buffer, char* postData, char* head);
//void httpdownSignedLength(char* data, char *domain, int port, char *uri, int length);
char* httpdown(char *domain, int port, char *uri, int *length, char *postData, char* head);
char* getHttpBody(char *data);
unsigned long getHttpHeaderEndPos(char *data);
int openRequestWithDest(char *domain, int port, char *uri, char *rtn, char* buffer, char* postData, struct sockaddr_in* dest, char* head) ;
struct sockaddr_in* getDest(char *domain, char *rtn, int port);
//int host2addr(const char *host, struct in_addr *addr);
char* dealTrunkedHttpData(char *data);


#include "httpdown.h"

#ifndef RECEIVE_BUF
#define RECEIVE_BUF 2048
#define DOWNLOAD_BUF 5120
#endif
/*
* @param domain www.abc.com
* @param port 80
* @param uri /index.html
* @param rtn 不要分配内存,函数内部会分配
* */
char* httpdown(char *domain, int port, char *uri, int *length, char *postData,
char* head) {
unsigned long buffer_len = 512 + strlen(uri) + strlen(domain);
if (postData != NULL)
buffer_len += strlen(postData);
if (buffer_len < RECEIVE_BUF)
buffer_len = RECEIVE_BUF;
char buffer[buffer_len];

char* rtn;
rtn = malloc(DOWNLOAD_BUF);
rtn[0] = 0;
(*length) = 0;
int sockfd = openRequest(domain, port, uri, rtn, buffer, postData, head);

#ifdef DEBUG
if (sockfd < 0) {
printf("[===HTTPDOWN===] Connect to %s:%d failed\n", domain, port);
*length = -1;
return rtn;
}
#else
if (sockfd < 0) {
*length = -1;
return rtn;
}
#endif

#ifdef DEBUG
printf("[===HTTPDOWN===] Init connect to %s:%d done, fd=%d\n", domain, port,
sockfd);
#endif

int dataLen = 0;
int current_buffer_size = DOWNLOAD_BUF;

long needLen, len = 0;
rtn[0] = 0;

buffer[0] = 0;
int type = -1;
int realloc_count = 1;
char * tmp;
while (1) {
len = recv(sockfd, buffer, RECEIVE_BUF, 0);
if (type < 0) {
tmp = strstr(buffer, "Content-Type");
if (tmp != NULL) {
tmp = strstr(tmp, "text");
if (tmp == NULL)
type = 1;
else
type = 0;
}
}
if (len > 0) {
needLen = dataLen + len;
/**
* 存在优化空间
* 1 根据content-length一开是就分配足够大空间
* 2 如果已经多次重新分配,则每次多分配一些
* 超大文件不适合此程序下载
*/
while (current_buffer_size <= needLen) {
current_buffer_size += DOWNLOAD_BUF * realloc_count;
#ifdef DEBUG
printf("[===HTTPDOWN===] realloc to %d\n", current_buffer_size);
#endif
rtn = realloc(rtn, current_buffer_size);
rtn[dataLen] = 0;
realloc_count++;
}

if (type < 1)
strncat(rtn + dataLen, buffer, len);
else
memcpy(rtn + dataLen, buffer, len);
dataLen += len;
} else {
if (len < 0) {
if(dataLen<1){
if (errno > 0)
sprintf(rtn, "消息接收失败!错误代码是%d,错误信息是'%s'\n", errno,
strerror(errno));
*length = -1;
}else{
tmp = strstr(rtn, "Content-Length: ");
if(tmp!=NULL){
char* tmp1 = strstr(tmp, "\r\n");
len = strlen(tmp)-strlen(tmp1)+1;
char tmpLen[32];

strncpy(tmpLen, tmp+16, len-16);

tmpLen[len-16] = 0;
len = atol(tmpLen);
#ifdef DEBUG
printf("len=%ld, tmpLen=%s\n", len, tmpLen);
#endif
tmp = strstr(rtn, "\r\n\r\n");

if(tmp!=NULL){
unsigned long contentLength = strlen(tmp)-4;
#ifdef DEBUG
printf("[===HTTPDOWN===] Header report length %ld, received length %ld\n", len, contentLength);
#endif
if(contentLength>=len){
*length = contentLength;
return rtn;
}
}
}else {
#ifdef DEBUG
printf("Content-Length not found\n");
#endif
if(dataLen>0){
rtn = dealTrunkedHttpData(rtn);
if(rtn!=NULL){
*length = strlen(rtn);
return rtn;
}
}
}
*length = -2;
}
return rtn;
}
#ifdef DEBUG
printf("[===HTTPDOWN===] Read data from %s:%d, complete\n", domain,
port);
#endif
break;
}
}

close(sockfd);
(*length) = dataLen;
return dealTrunkedHttpData(rtn);
}
struct sockaddr_in* getDest(char *domain, char *rtn, int port) {
struct sockaddr_in* dest;
dest = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
bzero(dest, sizeof(struct sockaddr_in));
dest->sin_family = AF_INET;
dest->sin_port = htons(port);
//	struct sockaddr_in addr;

//	if (inet_aton(domain, &addr.sin_addr) != 0) {
//		dest->sin_addr = addr.sin_addr;
//	} else {
struct hostent *host;
char **alias;
host = gethostbyname(domain);
if (host == NULL) {
sprintf(rtn, "@ @ No address information of %s\n%c", domain, 0);
return NULL;
} else {
for (alias = host->h_addr_list; *alias != NULL; alias++) {
dest->sin_addr = *(struct in_addr *) (*alias);
break;
}
}
/*int rs = host2addr(domain, &(dest->sin_addr));
if(rs!=0)
return NULL;*/
//	}
return dest;
}
//int host2addr(const char *host, struct in_addr *addr) {
//	struct hostent he, *result;
//	int herr, ret, bufsz = 512;
//	char *buff = NULL;
//	do {
//		char *new_buff = (char *) realloc(buff, bufsz);
//		if (new_buff == NULL) {
//			free(buff);
//			return ENOMEM;
//		}
//		buff = new_buff;
//		ret = gethostbyname_r(host, &he, buff, bufsz, &result, &herr);
//		bufsz *= 2;
//	} while (ret == ERANGE);
//	if (ret == 0 && result != NULL)
//		*addr = *(struct in_addr *) he.h_addr;
//		else if (result != &he)
//		ret = herr;
//	free(buff);
//	return ret;
//}
int openRequest(char *domain, int port, char *uri, char *rtn, char* buffer,
char* postData, char* head) {
struct sockaddr_in* dest = getDest(domain, rtn, port);
if (dest == NULL)
return -1;
return openRequestWithDest(domain, port, uri, rtn, buffer, postData, dest,
head);
}
int openRequestWithDest(char *domain, int port, char *uri, char *rtn,
char* buffer, char* postData, struct sockaddr_in* dest, char* head) {
if (uri[0] != '/')
printf(
"---------------======Error: Request Uri should start with \"/\"======---------------\n");
int sockfd;

/* 创建一个 socket 用于 tcp 通信 */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
free(dest);
printf(rtn, "@ @ Socket create error: %s!%c", strerror(errno), 0);
return -1;
}

struct timeval rcvto, sndto;
int tolen = sizeof(struct timeval);

rcvto.tv_sec = 5;
rcvto.tv_usec = 0;

sndto.tv_sec = 5;
sndto.tv_usec = 0;
//发送时限
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &sndto, tolen);
//接收时限
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &rcvto, tolen);
#ifdef DEBUG
printf("[===HTTPDOWN===] Will connect to %s:%d, to get %s\n", domain, port,
uri);
#endif
if (connect(sockfd, (struct sockaddr *) dest, sizeof(struct sockaddr))
!= 0) {
free(dest);
sprintf(rtn, "@ @ Socket create error: %s!%c", strerror(errno), 0);
return -1;
}

char postHeader[128];
postHeader[0] = 0;
if (postData != NULL && strlen(postData)>0) {
sprintf(postHeader,
"Content-Length: %ld\r\nContent-Type: application/x-www-form-urlencoded\r\n",
strlen(postData));
}

sprintf(buffer,
"%s %s HTTP/1.1\r\nHost: %s\r\n%s%sConnection: Close\r\n\r\n%s",
postData != NULL ? "POST" : "GET", uri, domain, postHeader,
head == NULL ? "" : head, postData != NULL && strlen(postData)>0 ? postData : "");

long len = send(sockfd, buffer, strlen(buffer), 0);
#ifdef DEBUG
printf(
"[===HTTPDOWN===] Send http request to %s:%d, data:\n---------------\n%s\n---------------\n",
domain, port, buffer);
#endif
if (len < 0) {
#ifdef DEBUG
if (errno > 0)
printf("[===HTTPDOWN===] Send http request to %s:%d, fail: %s\n",
domain, port, strerror(errno));
else
printf("[===HTTPDOWN===] Send http request to %s:%d, failed\n",
domain, port);
#endif
sprintf(rtn, "消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n%c", buffer, errno,
strerror(errno), 0);
free(dest);
return -1;
}
free(dest);
//free(host);
return sockfd;
}
char* getHttpBody(char *data) {
char* str = strstr(data, "\r\n\r\n");
if (str == NULL)
return data;
else
return str + 4;
}
unsigned long getHttpHeaderEndPos(char *data) {
char* str = strstr(data, "\r\n\r\n");
if (str == NULL)
return -1;
return strlen(data) - strlen(str) + 4;
}
//Transfer-Encoding: chunked
char* dealTrunkedHttpData(char *data) {
#ifdef DEBUG
printf("\nTotal= %ld\n", strlen(data));
#endif
char* str = strstr(data, "\r\n\r\n");
if (str == NULL || data == NULL || strlen(data) == 0)
return data;
char* header = malloc(strlen(data) - strlen(str) + 24);
header[0] = 0;
sstrncpy(header, data, strlen(data) - strlen(str) + 4);
#ifdef DEBUG
printf("\nHeader Len = %ld\n", strlen(header));
#endif
char* chunkedStr = strstr(header, "chunked");

if (chunkedStr == NULL) {
free(header);
return data;
} else {
unsigned long len = 0;

char* rtn = malloc(strlen(data));
char* tmp;
char* tmpLenStr = malloc(24);
tmpLenStr[0] = 0;
rtn[0] = 0;
strcpy(rtn, header);
free(header);
str = str + 4;
while ((tmp = strstr(str, "\r\n")) != NULL) {
len = strlen(str) - strlen(tmp);
strncpy(tmpLenStr, str, len);
tmpLenStr[len] = 0;
len = parse16(tmpLenStr);
#ifdef DEBUG
printf("LenStr %s len = %ld, len=%ld\n", tmpLenStr, strlen(tmpLenStr)+2,len);
#endif
if (len < 1)
break;

if(strlen(tmp+2)<len)
{
//接收数据中途断网,数据没有意义
printf("left data length less than %ld\n", len);
//len = strlen(tmp+2);
free(tmpLenStr);
free(data);
free(rtn);
return NULL;
}

strncat(rtn, tmp + 2, len);
str = tmp + 2 +len;
#ifdef DEBUG
printf("tmp len=%ld, len+2=%ld, str len=%ld\n", strlen(tmp),len+2, strlen(str));
#endif
}
free(tmpLenStr);
free(data);
return rtn;
}
}
/*
main ()
{
char rtn1[51200];
if(httpdown("baidu.com",80,"/index.html",rtn1)==1){
printf("OK: %d\n",strlen(rtn1));
}else{
printf("OK: %d\n",rtn1);
}
}
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐