下面例子中 :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 <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netdb.h>#define HOST "xx.xxx.xxx.xxx"
#define PORT 80
#define API "/test"struct resp_header{int status_code;//200char 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);}else{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");//headwrite(sockfd,str,strlen(str));//chunked 1char chunkdata1[128] = "Hello, world";char chunklength1[128] = {0};sprintf(chunklength1,"%x",strlen(chunkdata1));//chunklength1write(sockfd,chunklength1,strlen(chunklength1));write(sockfd,"\r\n",strlen("\r\n"));//chunkdata1write(sockfd,chunkdata1,strlen(chunkdata1));write(sockfd,"\r\n",strlen("\r\n"));//chunked 2char chunkdata2[128] = ",how are you";char chunklength2[128] = {0};sprintf(chunklength2,"%x",strlen(chunkdata2));//chunklength2write(sockfd,chunklength2,strlen(chunklength2));write(sockfd,"\r\n",strlen("\r\n"));//chunkdata2write(sockfd,chunkdata2,strlen(chunkdata2));write(sockfd,"\r\n",strlen("\r\n"));//chunked end 0write(sockfd,"0\r\n\r\n",strlen("0\r\n\r\n"));//response from servergetResponse(sockfd);close(sockfd);return 0;
}
运行效果如图:
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);}@Overridepublic 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