Transfer-Encoding chunked C写个解析

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define min(a,b) (a)<(b)?(a):(b)

int readline_sock(int sockfd,char* RecvData,int RecvLen)
{
	char tmp;
	int len = 0;
	int ret;
	while(len < RecvLen && (ret = recv(sockfd,&tmp,1,0)) == 1)
	{
		if(tmp == '\r')
			break;
		memcpy(RecvData + len,&tmp,1);
		len += 1;
	}
	if(ret != 1)
	{
		printf("readline err %d %s",errno,strerror(errno));
		return -1;
	}
	if(len == RecvLen)
		return len;
	if(tmp == '\r')
	{
		ret = recv(sockfd,&tmp,1,0);
		if(ret != 1)
		{
			printf("readline err %d %s",errno,strerror(errno));
			return -1;
		}
		else
		{
			return len;
		}
	}
}

int readbytes_sock(int sockfd,char* RecvData,int RecvLen)
{
	int len = 0,l = 0;
	
	while((len = recv(sockfd,RecvData + l,RecvLen - l,0)) > 0)
	{
		l += len;
	}
	if(len < 0)
		return len;
	return l;
}


int connect_alipay_new(char *host,int port,char *sendData,int sendData_len,char *recvData,int recvData_maxlen)
{
	int sockfd;
	struct hostent *phost = NULL;
	struct sockaddr_in sin;
	char tmp[0x8000 + 1];
	int tmp_len = 0;
	char name[100],value[100],*index1,*index2;
	
	int fd = 0;
	int recv_len = 0 ,len,len2;
	
	
	printf("gethostbyname start %s\n",__TIME__);
	phost = gethostbyname(host);
	if(phost ==NULL)	return;
	
	sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	printf("gethostbyname end ok %s\n",__TIME__);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr = *(struct in_addr*)phost->h_addr_list[0];
	
	printf("connect start %s\n",__TIME__);
	if(connect(sockfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
	{
		printf("connect err [%d] [%s]\n",errno,strerror(errno));
		exit(0);
	}
	printf("connect end ok %s\n",__TIME__);
	
	
	send(sockfd,sendData,sendData_len,0);
	
	memset(recvData,0,recvData_maxlen);
	
	memset(tmp,0,sizeof(tmp));
	tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
	if(tmp_len == -1)	return tmp_len;
	if(memcmp(tmp,"HTTP/1.1 200",12) != 0)
	{
		//recv_len = -1;
		//goto finish;
	}
	
	do
	{
		memset(tmp,0,sizeof(tmp));
		
		tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
		printf("lllll[%d][%s]\n",tmp_len,tmp);
		if(tmp_len <= 0)break;
		memset(name,0,sizeof(name));
		memset(value,0,sizeof(value));
		index1 = strchr(tmp,':');
		if(index == NULL)	break;
		strncpy(name,tmp,index1 - tmp);
		if(*(index1+1) == ' ')	index1++;
		strcpy(value,index1);
		printf("name:[%s] value[%s]\n",name,value);
		setenv(name,value,1);
	}while(1);
	
	memset(recvData,0,recvData_maxlen);
	
	
	if(tmp_len < 0)	
	{
		recv_len = -1;
		goto finish;
	}
	
	fd = open("log2",O_WRONLY|O_CREAT,0664);
	
	index1 = NULL;
	index1 = getenv("Transfer-Encoding");
	if(index1 != NULL)
	{
		recv_len = 0;
		while(1)
		{
			memset(tmp,0,sizeof(tmp));
			tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
			if(tmp_len == 0)
			{
				recv_len = -1;
				goto finish;
			}
			len = 0;
			sscanf(tmp,"%x",&len);
			
			printf("len:[%d]\ndata:[%s]",len,tmp);
			
			if(len == 0)
			{
				printf("finish\n");
				break;
			}
			memset(tmp,0,sizeof(tmp));
			tmp_len = 0;
			tmp_len = readbytes_sock(sockfd,tmp,len);
			if(tmp_len != len || tmp_len < 0)
			{
				printf("tmp_len != len,tmp_len=[%d] len=[%d]\n",tmp_len,len);
				recv_len = -1;
				goto finish;
			}
			else
			{
				write(fd,tmp,len);
				//memcpy(recvData + recv_len,tmp,len);
				recv_len += len;
			}
			tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
			if(tmp_len == 0)
				continue;
			else
				break;
		}
		goto finish;
	}
	
	index1 = NULL;
	index1 = getenv("Content-Length");
	if(index1 != NULL)
	{
		len = atol(index1);
		printf("Content-Lenght[%d]\n",len);
		if(len >= recvData_maxlen)
		{
			recv_len = -1;
			goto finish;
		}
		else
		{
			recv_len = readbytes_sock(sockfd,recvData,len);
			if(recv_len < len)
			{
				recv_len = -1;
				goto finish;
			}
			goto finish;
		}
	}
	

finish:

	close(sockfd);

	return recv_len;
	
}

int connect_alipay_fd(char *host,int port,char *sendData,int sendData_len,int fd)
{
	int sockfd;
	struct hostent *phost = NULL;
	struct sockaddr_in sin;
	char tmp[0x8000 + 1];
	int tmp_len = 0;
	char name[100],value[100],*index1,*index2;

	int recv_len = 0 ,len,len2;
	
	
	printf("gethostbyname start %s\n",__TIME__);
	phost = gethostbyname(host);
	if(phost ==NULL)	return;
	
	sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	printf("gethostbyname end ok %s\n",__TIME__);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr = *(struct in_addr*)phost->h_addr_list[0];
	
	printf("connect start %s\n",__TIME__);
	if(connect(sockfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
	{
		printf("connect err [%d] [%s]\n",errno,strerror(errno));
		exit(0);
	}
	printf("connect end ok %s\n",__TIME__);
	
	
	send(sockfd,sendData,sendData_len,0);
	
	
	memset(tmp,0,sizeof(tmp));
	tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
	if(tmp_len == -1)	return tmp_len;
	if(memcmp(tmp,"HTTP/1.1 200",12) != 0)
	{
		//recv_len = -1;
		//goto finish;
	}
	
	do
	{
		memset(tmp,0,sizeof(tmp));
		
		tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
		printf("lllll[%d][%s]\n",tmp_len,tmp);
		if(tmp_len <= 0)break;
		memset(name,0,sizeof(name));
		memset(value,0,sizeof(value));
		index1 = strchr(tmp,':');
		if(index == NULL)	break;
		strncpy(name,tmp,index1 - tmp);
		if(*(index1+1) == ' ')	index1+=2;
		else index1 +=1;
		strcpy(value,index1);
		printf("name:[%s] value[%s]\n",name,value);
		setenv(name,value,1);
	}while(1);
	
	
	
	
	if(tmp_len < 0)	
	{
		recv_len = -1;
		goto finish;
	}
	
	
	index1 = NULL;
	index1 = getenv("Transfer-Encoding");
	if(index1 != NULL && strcmp(index1,"chunked") == 0)
	{
		recv_len = 0;
		while(1)
		{
			memset(tmp,0,sizeof(tmp));
			tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
			if(tmp_len == 0)
			{
				recv_len = -1;
				goto finish;
			}
			len = 0;
			sscanf(tmp,"%x",&len);
			
			printf("len:[%d]\ndata:[%s]",len,tmp);
			
			if(len == 0)
			{
				printf("finish\n");
				break;
			}
			memset(tmp,0,sizeof(tmp));
			tmp_len = 0;
			tmp_len = readbytes_sock(sockfd,tmp,len);
			if(tmp_len != len || tmp_len < 0)
			{
				printf("tmp_len != len,tmp_len=[%d] len=[%d]\n",tmp_len,len);
				recv_len = -1;
				goto finish;
			}
			else
			{
				write(fd,tmp,len);
			}
			tmp_len = readline_sock(sockfd,tmp,sizeof(tmp));
			if(tmp_len == 0)
				continue;
			else
				break;
		}
		goto finish;
	}
	
	index1 = NULL;
	index1 = getenv("Content-Length");
	if(index1 != NULL)
	{
		len = atol(index1);
		printf("Content-Lenght[%d]\n",len);
		recv_len = 0;
		while(recv_len < len)
		{
			memset(tmp,0,sizeof(tmp));
			tmp_len = readbytes_sock(sockfd,tmp,min(len - recv_len,sizeof(tmp)-1));
			if(tmp_len < 0)
			{
				recv_len = -1;
				goto finish;
			}
			recv_len += tmp_len;
			write(fd,tmp,tmp_len);
		}
		goto finish;

	}
	

finish:

	close(sockfd);

	return recv_len;
	
}

int main()
{
	//char *host = "www.baidu.com";
	//int port = 80;
	char *host = "127.0.0.1";
	int port = 8888;
	
	int fd = open("log",O_WRONLY|O_CREAT|O_TRUNC,0664);
	
	int recv_len,len;
	char sendData[40960] = {0},recvData[40960] = {0};
	
	sprintf(sendData,"GET / HTTP/1.1\r\nAccept: */*\r\nAccept-Language: zh-Hans-CN, zh-Hans; q=0.8, en-US; q=0.5, en; q=0.3\r\nConnection: close\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134\r\n\r\n",host);
		
	//recv_len = connect_alipay_new(host,port,sendData,strlen(sendData),recvData,sizeof(recvData));
	recv_len = connect_alipay_fd(host,port,sendData,strlen(sendData),fd);
	close(fd);
	return;

	
	
}

部分代码参考自tinyhttpd https://github.com/EZLippi/Tinyhttpd

下面是用tornado实现的服务端,以分段传输Transfer-Encoding: chunked返回

import tornado
import tornado.web
import os
import socket
import multiprocessing
import time

port = 8888

class IndexHandler(tornado.web.RequestHandler):
	def get(self):
		for i in range(100):
			self.write('A'*0x8000)
			self.flush()

def main():
	sockets = tornado.netutil.bind_sockets(port,family = socket.AF_INET)
	app = tornado.web.Application([(r"/", IndexHandler,),])
	httpd = tornado.httpserver.HTTPServer(app)
	httpd.add_sockets(sockets)
	tornado.ioloop.IOLoop.current().start()

if __name__ == '__main__':
	main()

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值