zoukankan      html  css  js  c++  java
  • c实现的iOS http下载类。支持自己设定http 头(比如cookie等)

    也许有人要问为什么要自己用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
    ", (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
    ",start.tv_sec);
    //	printf("start.tv_usec:%d
    ",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
    ", filename, limit);
    			break;
    		}
    	}
    	free(buf);
    	//printf("Read %s, data length: %d
    ", filename, pos);
    	fclose(fp);
    	buffer[pos - 1] = '';
    	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
    ",argv[0]);
     exit(1);
     }
    
     printf("pos=%d
    ",strpos(argv[1],argv[2]));
     printf("replaced=%s
    ",replace(argv[1],argv[2],argv[3]));
    
     int ll=3;
     char **rtn=split(argv[1],argv[2],ll);
    
     while(ll>0){
     ll--;
     printf("%s
    ",*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
    ", 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
    ", 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
    ", 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'
    ", errno,
                                    strerror(errno));
                        *length = -1;
                    }else{
                        tmp = strstr(rtn, "Content-Length: ");
                        if(tmp!=NULL){
                            char* tmp1 = strstr(tmp, "
    ");
                            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
    ", len, tmpLen);
    #endif
                            tmp = strstr(rtn, "
    
    ");
                            
                            if(tmp!=NULL){
                                unsigned long contentLength = strlen(tmp)-4;
    #ifdef DEBUG
                                printf("[===HTTPDOWN===] Header report length %ld, received length %ld
    ", len, contentLength);
    #endif
                                if(contentLength>=len){
                                    *length = contentLength;
                                    return rtn;
                                }
                            }
                        }else {
    #ifdef DEBUG
                            printf("Content-Length not found
    ");
    #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
    ", 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
    %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 "/"======---------------
    ");
    	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
    ", 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
    Content-Type: application/x-www-form-urlencoded
    ",
    				strlen(postData));
    	}
    
    	sprintf(buffer,
    			"%s %s HTTP/1.1
    Host: %s
    %s%sConnection: Close
    
    %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:
    ---------------
    %s
    ---------------
    ",
    			domain, port, buffer);
    #endif
    	if (len < 0) {
    #ifdef DEBUG
    		if (errno > 0)
    			printf("[===HTTPDOWN===] Send http request to %s:%d, fail: %s
    ",
    					domain, port, strerror(errno));
    		else
    			printf("[===HTTPDOWN===] Send http request to %s:%d, failed
    ",
    					domain, port);
    #endif
    		sprintf(rtn, "消息'%s'发送失败!错误代码是%d,错误信息是'%s'
    %c", buffer, errno,
    				strerror(errno), 0);
    		free(dest);
    		return -1;
    	}
    	free(dest);
    	//free(host);
    	return sockfd;
    }
    char* getHttpBody(char *data) {
    	char* str = strstr(data, "
    
    ");
    	if (str == NULL)
    		return data;
    	else
    		return str + 4;
    }
    unsigned long getHttpHeaderEndPos(char *data) {
    	char* str = strstr(data, "
    
    ");
    	if (str == NULL)
    		return -1;
    	return strlen(data) - strlen(str) + 4;
    }
    //Transfer-Encoding: chunked
    char* dealTrunkedHttpData(char *data) {
    #ifdef DEBUG
    	printf("
    Total= %ld
    ", strlen(data));
    #endif
    	char* str = strstr(data, "
    
    ");
    	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("
    Header Len = %ld
    ", 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, "
    ")) != 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
    ", tmpLenStr, strlen(tmpLenStr)+2,len);
    #endif
                if (len < 1)
    				break;
                
                if(strlen(tmp+2)<len)
                {
                    //接收数据中途断网,数据没有意义
                    printf("left data length less than %ld
    ", 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
    ", 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
    ",strlen(rtn1));
     }else{
     printf("OK: %d
    ",rtn1);
     }
     }
     */
    
    



     

  • 相关阅读:
    分位数(quantiles)、Z-score 与 F-score
    学术研究中的 NLP
    学术研究中的 NLP
    国内外免费电子书(数学、算法、图像、深度学习、机器学习)
    国内外免费电子书(数学、算法、图像、深度学习、机器学习)
    中英文对照 —— 缩略词
    内核编译及模块相关命令使用
    UVA 156 (13.08.04)
    hdu3117之矩阵快速幂
    系统运维技巧(三)——利用dd命令临时增加交换分区
  • 原文地址:https://www.cnblogs.com/lein317/p/5067548.html
Copyright © 2011-2022 走看看