c客户端post chunked协议上传到服务器demo源码

下面例子中 :c 客户端采用 chunked协议上传到服务器,java 服务器返回的不是chunked 协议

chunked 编码协议格式参考 https://blog.csdn.net/wy5761/article/details/17568851

c 客户端 chunked 完整内容是 Hello, world,how are you 。分了2块上传 Hello, world 和 ,how are you

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define HOST "xx.xxx.xxx.xxx"
#define PORT 80
#define API "/test"

struct resp_header{
	int status_code;//200
    char content_type[128];//Content-Type: 
	long content_length;//Content-Length: 
};

static void get_resp_header(const char *response,struct resp_header *resp){
	//获取响应头的信息
	char *pos = strstr(response, "HTTP/");
	if (pos)
		sscanf(pos, "%*s %d", &resp->status_code);//返回状态码
	pos = strstr(response, "Content-Type:");//返回内容类型
	if (pos)
		sscanf(pos, "%*s %s", resp->content_type);
	pos = strstr(response, "Content-length:");//内容的长度(字节)
	if (pos)
		sscanf(pos, "%*s %ld", &resp->content_length);
}

static void getResponse( int socket_fd)//, char **text)
{
	/* receive the response */
    char * response=NULL;
    response=(char*)malloc(2048);
    if(response==NULL){
		return;
    }
    memset(response, 0, 2048);
    int length = 0,mem_size=2048;
    struct resp_header resp;
    int ret=0;
    while(1){
		ret = recv(socket_fd, response+length, 1,0);
		if(ret<=0)
			break;
		//找到响应头的头部信息, 两个"\r\n"为分割点
		int flag = 0;
		int i;
		for (i = strlen(response) - 1; response[i] == '\n' || response[i] == '\r'; i--, flag++);
		if (flag == 4)	  
			break;
		length += ret;
		if(length>=mem_size-1){
			break;
		}
	}
	printf("response head :%s \n",response);
	get_resp_header(response,&resp);
        printf("resp.Content_length = %ld status_code = %d\n",resp.content_length,resp.status_code);
	if(resp.status_code!=200||resp.content_length==0){
		free(response);
		return;
	}
	free(response);
	char *body = (char *)malloc(resp.content_length+1);
	memset(body,0,resp.content_length+1);
	if(body==NULL){
		return;
	}
	ret=0;
	length=0;
	while(1){
		ret = recv(socket_fd, body+length, resp.content_length-length,0);
		if(ret<=0){
			break;
		}
		length+=ret;
		if(length==resp.content_length)
			break;
	}
    printf("response body :%s\n",body);
    //*text = body;
}

static int get_connect_socket_fd(char *host,int port)
{
    
    int sockfd;
    struct hostent *server;
    struct sockaddr_in serv_addr;
    
    /* create the socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
	printf("ERROR opening socket\n");
        return -1;
    }
    /* lookup the ip address */
    server = gethostbyname(host);
    if (server == NULL) 
    {
       printf("ERROR, no such host \n");
       return -1;
    }

    /* fill in the structure */
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);

    /* connect the socket */
    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
    {
        printf("ERROR connecting \n");
        return -1;
    }
    return sockfd;   
}

int main(int argc, char **argv)
{
	int sockfd;
	sockfd = get_connect_socket_fd(HOST,PORT);
	if(sockfd == -1){
		printf("get_connect_socket_fd error!!!");
		return 0;
	}
	
	char str[4096];
	memset(str, 0, 4096);
	
	sprintf(str,"POST %s HTTP/1.1\r\n",API);
	strcat(str, "Host: ");
	strcat(str, HOST);
	strcat(str, "\r\n");
	//strcat(str, "Content-Type: application/x-www-form-urlencoded\n");
	strcat(str, "Content-Type: application/octet-stream;charset=utf-8\r\n");
	strcat(str, "Transfer-Encoding: chunked\r\n");
	strcat(str, "Connection: keep-alive\r\n");
	strcat(str, "Content-Transfer-Encoding: binary\r\n");
	strcat(str, "Accept-Ranges: bytes\r\n");
	strcat(str, "\r\n");
	
	//head
	write(sockfd,str,strlen(str));
	
	//chunked 1
	char chunkdata1[128] = "Hello, world";
	char chunklength1[128] = {0};
	sprintf(chunklength1,"%x",strlen(chunkdata1));
	//chunklength1
	write(sockfd,chunklength1,strlen(chunklength1));
	write(sockfd,"\r\n",strlen("\r\n"));
	//chunkdata1
	write(sockfd,chunkdata1,strlen(chunkdata1));
	write(sockfd,"\r\n",strlen("\r\n"));
	
	//chunked 2
	char chunkdata2[128] = ",how are you";
	char chunklength2[128] = {0};
	sprintf(chunklength2,"%x",strlen(chunkdata2));
	//chunklength2
	write(sockfd,chunklength2,strlen(chunklength2));
	write(sockfd,"\r\n",strlen("\r\n"));
	//chunkdata2
	write(sockfd,chunkdata2,strlen(chunkdata2));
	write(sockfd,"\r\n",strlen("\r\n"));
	

	//chunked end 0
	write(sockfd,"0\r\n\r\n",strlen("0\r\n\r\n"));

	//response from server
	getResponse(sockfd);
	
	close(sockfd);
	return 0;
}


运行效果如图:
c客户端post chunked协议上传到服务器demo源码_第1张图片

java 服务器 接收chunked 协议上传的内容 代码 参考我之前的文章 提供的http服务器代码
https://blog.csdn.net/a704397849/article/details/88079945

HttpCmd 里面有个方法 readTrunkTest() 可以读取 chunked 内容

服务器端 读取c 客户端chunked上传的内容 的主要代码如下(框架代码在上述连接中) :

import frame.http.HttpCmd;


public class HttpCmdTest extends HttpCmd {
    static {
        HttpCmd.register("/chunked/test",HttpCmdTest.class);
    }

    @Override
    public void execute() {
        int size = 0;
        byte[] bytes = readTrunkTest();
        String s = "";
        if(bytes != null){
            size = bytes.length;
            try {
                s = new String(bytes, "utf-8");
            }catch (Exception e){

            }
        }

        response("{request body size = " + size + " , str = " + s +  "}");
    }
}

最后,如果c客户端想要实现解析来自服务器的chunked协议内容 ,下面地址 返回的就是chunked协议内容,可以用这个来调试开发
http://www.httpwatch.com/httpgallery/chunked/chunkedimage.aspx

你可能感兴趣的:(嵌入式,chunked)