使用C套接字在HTTP响应中发送二进制文件

我试图在http响应中发送二进制文件(png图像)。

FILE *file; char *buffer; int fileLen; //Open file file = fopen("1.png", "rb"); if (!file) { return; } //Get file length fseek(file, 0, SEEK_END); fileLen=ftell(file); fseek(file, 0, SEEK_SET); //Allocate memory buffer=(char *)malloc(fileLen+1); if (!buffer) { fprintf(stderr, "Memory error!"); fclose(file); return; } //Read file contents into buffer fread(buffer, fileLen, 1, file); fclose(file); //free(buffer); char header[102400]; sprintf(header, "HTTP/1.1 200 OK\n" "Date: Thu, 19 Feb 2009 12:27:04 GMT\n" "Server: Apache/2.2.3\n" "Last-Modified: Wed, 18 Jun 2003 16:05:58 GMT\n" "ETag: \"56d-9989200-1132c580\"\n" "Content-Type: image/png\n" "Content-Length: %i\n" "Accept-Ranges: bytes\n" "Connection: close\n" "\n", fileLen); char *reply = (char*)malloc(strlen(header)+fileLen); strcpy(reply, header); strcat(reply, buffer); printf("msg %s\n", reply); //return 0; int sd = socket(PF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(8081); addr.sin_addr.s_addr = INADDR_ANY; if(bind(sd,&addr,sizeof(addr))!=0) { printf("bind error\n"); } if (listen(sd, 16)!=0) { printf("listen error\n"); } for(;;) { int size = sizeof(addr); int client = accept(sd, &addr, &size); if (client > 0) { printf("client connected\n"); send(client, reply, strlen(reply), 0); } } 

但是我的浏览器不理解这个=(我到底做错了什么?

UPD:我试图发送文本数据 – 没关系。 但二进制数据失败了

问题是你的消息体被视为一个以空字符结尾的文本字符串(你使用strcatstrlen ),当它不是一个时:它是二进制数据(PNG文件)。 因此, strcatstrlen都停止在图像的前0个字节上(通常很早)。

你的程序甚至打印出响应体:注意它给出了正确的头,但是一旦PNG头(二进制数据)启动,只有几个字节。

  1. strcat(reply, buffer) ,其中buffer可能包含0个字节。 将其更改为memcpy(reply+strlen(header), buffer, fileLen)
  2. send(client, reply, strlen(reply), 0) ,其中reply可能包含0个字节。 预先计算回复的长度,或用strlen(header)+fileLen替换strlen。

另一个错误是,当你完成后你没有关闭连接,所以浏览器将永远等待。 你需要这个, send后:

 close(client); 

HTTP协议指定它期望“\ r \ n”而不是“\ n”。 试试吧。 🙂

 strcat(reply, buffer); // this is incorrect, because png(buffer) may contain zero byte send(client, reply, strlen(reply), 0); strlen(reply) // this is incorrect, because png may contain zero byte 

我试着按照你的所作所为,但无法让它发挥作用。 相反,我发现单独发送标题和文件更容易。

例如

 send(client, header, strlen(header), 0); send(client, buffer, fileLen + 1, 0);