也许有人要问为什么要自己用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等)的更多相关文章

  1. ios 后台下载,断点续传总结

    2018年12月05日 16:09:00 weixin_34101784 阅读数:5 https://blog.csdn.net/weixin_34101784/article/details/875 ...

  2. 移植samba到ios平台,最新支持ios8.3

    移植samba到ios平台,最新支持ios8.3 下载https://github.com/kolyvan/kxsmb 开源项目 1  cd samba-4.1.14 2  vi Rakefile 修 ...

  3. C# http下载(支持断点续传)

    分享下项目里面自己封装的一个http下载类 功能如下: 1.支持断点续传 2.下载失败自动重试 3.超时等异常处理 using System; using System.Collections.Gen ...

  4. 如何为ios酷我音乐盒下载导出的音乐文件(使用Java程序设计)

    这个工具已经准备第二版,读者了解编程软件,可以直接使用,请阅读和使用这个场地 http://blog.csdn.net/jzj1993/article/details/44459983 本文所涉及内容 ...

  5. IOS上传图片方法类

    IOS上传图片方法类   iPhone开发中遇到上传图片问题,找到多资料,最终封装了一个类,请大家指点,代码如下 // // RequestPostUploadHelper.h // demodes ...

  6. 【微信要跪】 iOS 应用如何完全支持 IPv6-ONLY 网络?

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  7. iOS NSURLSession 下载

    周五的时候,有个新的需求,要下载脚本,帮助玩家自动打怪,应该也是挂机的意思吧! 组长让我设计界面,让汤老师设计数据等.我觉得数据的挑战性更大一点,然后就接过来了. 自己还没有形成互联网思维,所以弄了一 ...

  8. 打印 上一主题 下一主题 利用cURL实现单个文件分多段同时下载,支持断点续传(修订版)

      利用cURL实现单个文件分多段同时下载,支持断点续传(修订版) [复制链接] 摘自 http://bbs.chinaunix.net/thread-917952-1-1.html 在ubuntu下 ...

  9. 下载类网站的SEO优化方面技巧

    在互联网国际中有一类十分主要的网站,那即是供应各种软件下载的网站,这类网站可以协助用户解决许多软件运用方面的疑问,可是随着知识产权维护的认识越来越强,许多下载类网站也要开端改动自个的经营策略,这么才可 ...

随机推荐

  1. andriod之摄像头驱动流程

    camera成像原理: 景物通过镜头生产光学图像投射到sensor表面上,然后转为模拟电信号,经过数模变成数字图像信号,在经过DSP加工出来,然后在通过IO接口传输到CPU处理. 由于摄像头满足总线. ...

  2. u盘在电脑读不出来,但别的可以读,别的u盘在我电脑又可以识别怎么回事?

    不知道我的U盘是怎么回事,在我自己的电脑里读不出来,下面有U盘图标,但我的电脑里就是找不到U盘盘符,但把这个U盘放其他电脑上又可以读取,我以为是我的电脑的问题,但用其他的U盘插我电脑又没问题,完全摸不 ...

  3. Python学习笔记4—列表

    列表定义 >>> a=['] >>> type(a) <type 'list'> >>> bool(a) #列表有值,则为true T ...

  4. Linux之top命令

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.下面详细介绍它的使用方法.top是一个动态显示过程,即可以通过用户按键来不断刷新 ...

  5. 【夯实Mysql基础】记一次mysql语句的优化过程!

      1. [事件起因] 今天在做项目的时候,发现提供给客户端的接口时间很慢,达到了2秒多,我第一时间,抓了接口,看了运行的sql,发现就是 2个sql慢,分别占了1秒多. 一个sql是 链接了5个表同 ...

  6. laravel各种路径的获取方法

    若Route中有Route::get('home/test', 'HomeController@index')->name('test'); ①视图中的href跳转 一.<a href=& ...

  7. eclipse_中的注释_快捷键

    eclipse 中的注释 快捷键   把要注释的代码选中,按Ctrl+Shift+/ /* */ 形式的 ctrl+/ //形式的 取消代码注释: 把要注释的代码选中,按Ctrl+Shift+\ /* ...

  8. SDL2.0的几何图行绘画

    SDL2.0的几何图形绘画 通过SDL_Window.SDL_Renderer.SDL_Texture三者实现了简单的几何图形绘画. 包括了SDL_RenderDrawPoint.SDL_Render ...

  9. .NET简谈反射(动态调用)

    我们继续C#基础知识的学习,这篇文章主要要讲的是我们C#程序员迈向高级C#程序员的关键性的一步. 有的朋友会说事实不是这样的,我不用反射就不能开发吗?当然可以,但是用与不用肯定是不一样的,任何复杂抽象 ...

  10. ma

    首页 第一项 上课 哈哈