Reputation: 480
I am trying to simulate client/server communication to send and receive files using sockets and http requests.
The client sends an http request to the server saying that they want to download a simple .txt file and the server sends the file data back to the client with an http response header.
However, the data written into the received text file also contains the http header information which it shouldn't.
How do I effectively separate the http header from the actual data?
Here's what the code looks like:
Server:
//receives an http header request from client saying they want to download a .txt file
bzero(buffer, 256);
sprintf(buffer, "HTTP/1.1 200 OK\r\n Date:%s\r\n Content-Type:%s\r\n Content-Length:%s\r\n\r\n", time, content, length);
data = write(incoming_socket, buffer, strlen(buffer)); // first sends an http response header
bzero(buffer, 256);
int data;
while((data = fread(buffer, sizeof(char), 256, fs)) > 0){
if(send(cli_socket, buffer, strlen(buffer), 0) < 0){ // sends the actual file data to client in this while cycle
perror("ERROR: Could not send file.");
break;
exit(EXIT_FAILURE);
}
if (block_size < 256){
if (ferror(fs)){
perror("ERROR: Failed while sending data.");
exit(EXIT_FAILURE);
}
bzero(buffer, 256);
break;
}
bzero(buffer, 256);
}
Client:
bzero(buffer, 256);
data = read(client_socket, buffer, 256); // first receive the http header response
bzero(buffer, 256);
while (1){
data = recv(client_socket, buffer, 256, 0); // receive data
fwrite(buffer, sizeof(char), data, fr); // write data into the file
bzero(buffer, 256);
if (data == 0 || data < 256){
fclose(fr);
break;
}
if(data< 0){
printf("failed while copyng file!\n");
exit(1);
}
}
However, this fills the .txt file with the http response as well, not just the data.
Now, I know that I should probably look for /r/n/r/n in the header response in order to separate the header and write just the actual data but, if someone could show me the best way to do this in my example with my particular buffer, I'd be very grateful!
Upvotes: 0
Views: 2665
Reputation: 182753
Unfortunately, you've chosen a very compelex protocol to implement. Your only choice is to read the documentation for HTTP version 1.1 and follow the specification precisely. The documentation will tell you how to identify the end of the header. Note that you must support chunked encoding. It is required for HTTP 1.1 compliance.
But you've really chosen an H-bomb to kill an ant here. HTTP 1.1 is a complex, high-performance protocol and a terrible choice for just messing around transferring a file.
A few more mistakes:
if(send(cli_socket, buffer, strlen(buffer), 0) < 0){ // sends the actual file data to client in this while cycle
The strlen
function is only for C-style strings, not arbitrary data. The recv
function returns the number of bytes read for a reason.
data = recv(client_socket, buffer, 256, 0); // receive data
fwrite(buffer, sizeof(char), file_block_size, fr); // write data into the file
Surely the number of bytes you write should be the number of bytes you read (which you helpfully stored in a variable, data
, but didn't use), not some other number.
If you really want to make HTTP 1.1 client and server code, you really should start by thoroughly understanding both the HTTP 1.1 specification and example client and server code. But that's a terrible way to learn how to send and receive files because HTTP 1.1 is so complicated.
Upvotes: 2