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来实现。
上代码,造福百姓:
原因是:
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); } } */
相关文章推荐
- c实现的iOS http下载类。支持自己设定http 头(比如cookie等)
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类
- C#实现http协议支持上传下载文件的GET、POST请求
- C#实现http协议支持上传下载文件的GET、POST请求
- IOS开发网络篇之──ASIHTTPRequest下载示例(支持断点续传)
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (第2版) (C# DIY HttpWebClient)
- Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (转,尚未整理)
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (C# DIY HttpWebClient)
- IOS开发网络篇之──ASIHTTPRequest下载示例(支持断点续传)
- [收藏]实现支持断点续传多线程下载的 Http Web 客户端工具类 (第2版)
- /* .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类【转】
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (第2版) (C# DIY HttpWebClient)
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (第2版) (C# DIY HttpWebClient)
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (C# DIY HttpWebClient)
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (第2版) (C# DIY HttpWebClient) 收藏
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (第2版) (C# DIY HttpWebClient)
- C#.Net: 实现支持断点续传多线程下载的 Http Web 客户端工具类
- .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (C# DIY HttpWebClient)
- org.apache.tools.zip.*和org.apache.commons.httpclient.*实现远程文件打包下载,支持中文文件名(转)
- (转)IOS开发网络篇之──ASIHTTPRequest下载示例(支持断点续传)