我是靠谱客的博主 长情铃铛,最近开发中收集的这篇文章主要介绍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=%ldn", (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:%dn",start.tv_sec);
//	printf("start.tv_usec:%dn",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 %dn", filename, limit);
			break;
		}
	}
	free(buf);
	//printf("Read %s, data length: %dn", 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 str2n",argv[0]);
 exit(1);
 }

 printf("pos=%dn",strpos(argv[1],argv[2]));
 printf("replaced=%sn",replace(argv[1],argv[2],argv[3]));

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

 while(ll>0){
 ll--;
 printf("%sn",*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 failedn", 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=%dn", 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 %dn", 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, "rn");
                        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=%sn", len, tmpLen);
#endif
                        tmp = strstr(rtn, "rnrn");
                        
                        if(tmp!=NULL){
                            unsigned long contentLength = strlen(tmp)-4;
#ifdef DEBUG
                            printf("[===HTTPDOWN===] Header report length %ld, received length %ldn", len, contentLength);
#endif
                            if(contentLength>=len){
                                *length = contentLength;
                                return rtn;
                            }
                        }
                    }else {
#ifdef DEBUG
                        printf("Content-Length not foundn");
#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, completen", 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 %sn%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 %sn", 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: %ldrnContent-Type: application/x-www-form-urlencodedrn",
				strlen(postData));
	}

	sprintf(buffer,
			"%s %s HTTP/1.1rnHost: %srn%s%sConnection: Closernrn%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%sn---------------n",
			domain, port, buffer);
#endif
	if (len < 0) {
#ifdef DEBUG
		if (errno > 0)
			printf("[===HTTPDOWN===] Send http request to %s:%d, fail: %sn",
					domain, port, strerror(errno));
		else
			printf("[===HTTPDOWN===] Send http request to %s:%d, failedn",
					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, "rnrn");
	if (str == NULL)
		return data;
	else
		return str + 4;
}
unsigned long getHttpHeaderEndPos(char *data) {
	char* str = strstr(data, "rnrn");
	if (str == NULL)
		return -1;
	return strlen(data) - strlen(str) + 4;
}
//Transfer-Encoding: chunked
char* dealTrunkedHttpData(char *data) {
#ifdef DEBUG
	printf("nTotal= %ldn", strlen(data));
#endif
	char* str = strstr(data, "rnrn");
	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 = %ldn", 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, "rn")) != NULL) {
			len = strlen(str) - strlen(tmp);
			strncpy(tmpLenStr, str, len);
			tmpLenStr[len] = 0;
			len = parse16(tmpLenStr);
#ifdef DEBUG
			printf("LenStr %s len = %ld, len=%ldn", tmpLenStr, strlen(tmpLenStr)+2,len);
#endif
            if (len < 1)
				break;
            
            if(strlen(tmp+2)<len)
            {
                //接收数据中途断网,数据没有意义
                printf("left data length less than %ldn", 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=%ldn", 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: %dn",strlen(rtn1));
 }else{
 printf("OK: %dn",rtn1);
 }
 }
 */



 

转载于:https://www.cnblogs.com/lein317/p/5067548.html

最后

以上就是长情铃铛为你收集整理的c实现的iOS http下载类。支持自己设定http 头(比如cookie等)的全部内容,希望文章能够帮你解决c实现的iOS http下载类。支持自己设定http 头(比如cookie等)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部