Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
HTTP Request in C using low level write to socket functionality
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
int socket_connect(char *host, in_port_t port){
struct hostent *hp;
struct sockaddr_in addr;
int on = 1, sock;
if((hp = gethostbyname(host)) == NULL){
herror("gethostbyname");
exit(1);
}
bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(int));
if(sock == -1){
perror("setsockopt");
exit(1);
}
if(connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1){
perror("connect");
exit(1);
}
return sock;
}
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]){
int fd;
char buffer[BUFFER_SIZE];
if(argc < 3){
fprintf(stderr, "Usage: %s <hostname> <port>\n", argv[0]);
exit(1);
}
fd = socket_connect(argv[1], atoi(argv[2]));
write(fd, "GET /\r\n", strlen("GET /\r\n")); // write(fd, char[]*, len);
bzero(buffer, BUFFER_SIZE);
while(read(fd, buffer, BUFFER_SIZE - 1) != 0){
fprintf(stderr, "%s", buffer);
bzero(buffer, BUFFER_SIZE);
}
shutdown(fd, SHUT_RDWR);
close(fd);
return 0;
}
@sebitoelcheater

This comment has been minimized.

Copy link

commented Sep 21, 2014

nice work! how can I go to for example, localhost:3000/something ?

@TylerTemp

This comment has been minimized.

Copy link

commented Jun 24, 2016

@sebitoelcheater

gcc socket.c -o soc
./soc https://www.google.com 80
@dimuthnc

This comment has been minimized.

Copy link

commented Dec 1, 2016

I tried to call localhost:8080/services from this. It fails in every way. Can you please help me?

@fxfactorial

This comment has been minimized.

Copy link

commented Dec 26, 2016

@dimuthnc change the code to give 127.0.0.1 for whenever host is localhost

@Matrixbirds

This comment has been minimized.

Copy link

commented Jan 27, 2017

why use PF_INET for create sock.. addr structure be set by AF_INET..

@alr-lab

This comment has been minimized.

Copy link

commented Feb 28, 2017

@sebitoelcheater and @dimuthnc you need to modify the request header https://gist.github.com/nolim1t/126991#file-socket-c-L53 to something such as GET /something HTTP/1.1\r\n, maybe create a #define if you want to use it everytime OR change the code so it accept a third argument (or parse it from the complete URI): the suffix URI - the requested page.

The GET /\r\n in this Gist will ask for the index page (/) if any.

Reminder: a minimal header may look like:

GET /something HTTP/1.1\r\n
Host: www.42.fr\r\n
\r\n

which, if successfully sent, will trigger a request to a web server located at www.42.fr to get the /something page using the GET HTTP method. Note the double \r\n line ending, ending the header.

I hope this will help you!
Happy coding everyone

@minhnv-viosoft

This comment has been minimized.

Copy link

commented May 15, 2017

I've used your code to get a text file ( about 70KB)
It run through the while loop about 25 times,
but the last loop it seem very slow , I think it's been blocking somewhere ( maybe in read function). please help me to explain .

example the file :
http://super-pomoyka.us.to//trash/ttv-list/ttv.m3u

@RossignolVincent

This comment has been minimized.

Copy link

commented Jun 12, 2017

Hello, i try to run this code on the Star Wars API (https://swapi.co/) but it doesn't work. I've tried multiple configurations :

./api swapi.co/ 80
gethostbyname: Unknown host
./api http://swapi.co/api/people/1/ 80
gethostbyname: Unknown host

Even with you example with google.com, i've got the same error message. Do you know why ?

@Cannedfood

This comment has been minimized.

Copy link

commented Jun 28, 2017

@RossignolVincent Have you tried www.swapi.co?

@mudiadamz

This comment has been minimized.

Copy link

commented Jul 21, 2017

what if the response is 302 redirection,
how to make a request to new location?

@ajvuik

This comment has been minimized.

Copy link

commented Sep 19, 2017

Thank for this. I used this in conjuction with Arduino Json to get the local weather from http://openweathermap.org. Works like a treat 👍

@wb-towa

This comment has been minimized.

Copy link

commented Sep 30, 2017

gethostbyname() isn't very futureproof. gethostbyname2() will at least let you opt for ipv4 or ipv6

As alr-lab pointed out the headers are incomplete.

I think most of the problems people are experiencing is down to not understanding the code (i.e. including the http and ending slash rather than just www.google.com) so it may have been nicer to include some examples or comments. Of course this is 8 years old too so understandably it may not hold up as well now.

It is a good pointer in the right direction but learners will need to work on it bit.

@hebrerillo

This comment has been minimized.

Copy link

commented Nov 26, 2017

When I try to get this url "http://www.cplusplus.com/" the webserver performs a 301 redirection to the same url.

Why? What am I doing wrong?

This is the command line I am executing:

./a.out www.cplusplus.com 80

Thanks a lot!

@hebrerillo

This comment has been minimized.

Copy link

commented Nov 26, 2017

Hi everyone!

I found the solution, the get request should be like this :

"GET / HTTP/1.0\r\nHost: www.cplusplus.com\r\n\r\n\r\n"

All the best!

@itsKindred

This comment has been minimized.

Copy link

commented Jan 31, 2019

It looks like the GET request is missing a second \r\n. HTTP Requests require a blank line at the end. If you do a raw nc to a web server, and send "GET /" and press enter, you wont get a response. Once hitting enter again, however, you will get a response. This is due to that second \r\n being needed. write(fd, "GET /\r\n", strlen("GET /\r\n")); // write(fd, char[], len); should actually be write(fd, "GET /\r\n\r\n", strlen("GET /\r\n\r\n")); // write(fd, char[], len);

@samofta

This comment has been minimized.

Copy link

commented Feb 9, 2019

This doesn't work on Mac. I keep getting an error:

Undefined symbols for architecture x86_64:
  "_copy", referenced from:
      _socket_connect in msgario-a206e2.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
@samofta

This comment has been minimized.

Copy link

commented Feb 10, 2019

This code snippet should use bcopy() instead of copy(). copy() doesn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.