I'm following a tutorial for creating an HTTP server with sockets using C. I'm on Windows using the gcc compiler. The server runs and I can even hit it and get data back when using a custom client built from C sockets. But When I try run the command
"curl -o - http://127.0.0.1:8001"
to connect to my server, I receive the error:
curl : Unable to read data from the transport connection: An existing connection was forcibly closed by the remote
host.
My server output shows the connection is trying to be made, but doesn't show any errors. Here is my code.. http_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
int main()
{
//open a file to server
FILE *html_data;
html_data = fopen("index.html", "r");
char response_data[1024];
fgets(response_data, 1024, html_data);
char http_header[2048] = "HTTP/1.1 200 OK\r\n\r\n";
strcat(http_header, response_data);
//create a socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM,0);
// specify an address for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
server_address.sin_addr.s_addr = INADDR_ANY;
//bind the socket to our specified IP and port
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
listen(server_socket,5);
int client_socket;
while(1) {
client_socket = accept(server_socket, NULL, NULL);
printf("client socket response: %d\n", client_socket);
perror("socket");
send(client_socket, http_header, sizeof(http_header),0);
close(client_socket);
}
return 0;
}
index.html
<html><body>welcome to the HTTP Server!</body></html>
I think you're pretty close to getting it working. The reason curl
is complaining is because it's expecting you to have supplied a Content-Length
header. You can do this by updating your existing code as follows:
char response_data[1024];
fgets(response_data, 1024, html_data);
size_t message_length = strlen(response_data);
char http_header[2048];
snprintf(http_header, sizeof(http_header), "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n", message_length);
strcat(http_header, response_data);
You also need to update your send code to only send the length of the response string.
send(client_socket, http_header, strlen(http_header),0);
You still have some issues with your error checking as mentioned in the comments, but at least with these changes curl
should be happy.
While what I mentioned above is the minimal headers that will satisfy curl
, there are others that you need to add to make you code conform to Hypertext Transfer Protocol -- HTTP/1.1
Connection: close
Content-Type: text/html