nanjero echizen nanjero echizen - 2 months ago 6
C Question

C - How can I read the returned values of a HTTP GET request line by line?

My goal is to read the returned http status code (very first line returned) after the get request. Then if the status code is 200 then print the rest of the message otherwise only print the status code. How can I achieve this?

My current code returns the whole webpage:

main(int argc, char *argv[])
{
int csd;
struct sockaddr_in server;
struct hostent *server_host;
int server_len;
int string_size;
short server_port;
char req_buffer[BUF_LEN];
char temp_buffer[BUF_LEN];
char receiveBuffer[BUF_LEN];
char resource_buffer[BUF_LEN];
int t;
int chars_read;

if(argc!=2)
{
fprintf(stderr,"Usage: %s <website> \n",argv[0]);
exit(EXIT_FAILURE);
}

server_host=gethostbyname(argv[1]);
if (server_host == NULL)
{
herror("While calling gethostbyname()");
exit(EXIT_FAILURE);
}

csd=socket(PF_INET, SOCK_STREAM, 0);
if(csd<0)
{
perror("While calling socket()");
exit(EXIT_FAILURE);
}

server.sin_family=AF_INET;
memcpy(&server.sin_addr, server_host->h_addr_list[0], server_host->h_length);
server.sin_port = htons(80);
server_len=sizeof(server);
t = connect(csd, (struct sockaddr *) &server, server_len);
if (t<0)
{
perror("while connecting()");
exit(EXIT_FAILURE);
}
else
{
printf("connected to server\n\n");
}

sprintf(temp_buffer, "GET / HTTP/1.0\r\n");
strcpy(req_buffer, temp_buffer);
sprintf(temp_buffer, "HOST: %s\r\n", argv[1]);
strcat(req_buffer, temp_buffer);
sprintf(temp_buffer, "\r\n");
strcat(req_buffer, temp_buffer);

printf(req_buffer);

write(csd, req_buffer, strlen(req_buffer));

while (1)
{
chars_read = read(csd, receiveBuffer, 10000);
if (chars_read == 0)
return;
fwrite (receiveBuffer, sizeof (receiveBuffer), chars_read, stdout);
}

close(csd);
}


Also when I run this I get 2 weird outputs. First is the weird letters positioned in a weird format. Second is there is a long intangible code thing at the start of my new input line. like so: ([username@han ~Desktop]$ (long wierd wierd code thing here))

Answer

If csd were a file handle instead of a file descriptor, I'd suggest using fgets to process the input stream line by line.

But it's not :-)

So you have (at minimum) a couple of options.

First, you could read character by character, adding it to a buffer, then, when you read a newline, pass said buffer to a function to handle the enire line before zeroing out the buffer and continuing.

Or you could read the entire message and post-process it in a similar manner, looking for embedded newlines and passing the relevant portion (ie, a line) to a function for processing.


In terms of your dodgy characters, that could be caused by many things but I'd be looking out for (again, at a minimum):

  • printf with an uncontrolled string. The correct way of doing this is printf("%s", dodgyString) to ensure that any % characters in the string don't cause problems.
  • Making a buffer of size BUF_LEN then using 10000 as a limit on it. You should really use BUF_LEN as the limit.
  • the parameters to fwrite. You should either use a unit size of 1 and unit count of chars_read, or the other way around. Writing BUF_LEN * chars_read characters when you've only read chars_read is going to cause you problems.
Comments