Send binary in HTTP response using C sockets

I am trying to send a binary file (png image) in an http response.

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); } } 

but my browser doesn’t understand this = (What am I doing wrong?

UPD: I tried to send text data - this is OK. But binary data fails

+6
c binary sockets send
source share
4 answers

The problem is that the body of your message is treated as a zero-terminated text string (you use strcat and strlen on it) when it is not one: it is binary data (PNG file), therefore strcat and strlen both stop at the first 0 bytes of the image (usually pretty early).

Your program even prints the response body: note that it gives the correct header, but after launching the PNG header (binary data) there are only a few bytes.

  • String strcat(reply, buffer) , where buffer potentially contains 0 bytes. Change it to memcpy(reply+strlen(header), buffer, fileLen) .
  • The string send(client, reply, strlen(reply), 0) , where reply potentially contains 0 bytes. Pre-calculate the length of the response or replace strlen with strlen(header)+fileLen .

Another mistake is that you do not close the connection when you are ready, so the browser will just wait. You need this after send :

 close(client); 
+7
source

The HTTP protocol indicates that it expects "\ r \ n" instead of "\ n". Try this.:)

+1
source
 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 
0
source

I tried to keep track of what you did, but couldn't get it to work. Instead, it was easier for me to simply send the header and file separately.

eg.

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

All Articles