C: Linux Socket Programming, TCP, a simple HTTP client
Articles may may have files attached at the end of the post
Linux provide a high level socket API that will allow programmer to easily connect to any TCP or UDP services.
In this tutorial, we will see how this works by implementing a simple HTTP client which will get request a web page given the hostname and the page name, then read the server answer and output the HTML content of the reply.
To be able to connect to a service built on top of TCP, we first need to create a socket for the TCP protocol, fill in a network address structure representing our destination and the port to connect to and use the latter to connect to the remote server.
From there, we will be able to send and receive data over the network. Once we are done, we will close the connection.
Below is the C code for a simple HTTP client that will get the host and the page to request from the command line arguments, resolve the hostname name to an IP, connect to this IP on port 80, build the HTTP query, send it and the retrieve the page content.
- #include <stdio.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <stdlib.h>
- #include <netdb.h>
- #include <string.h>
- int create_tcp_socket();
- char *get_ip(char *host);
- char *build_get_query(char *host, char *page);
- void usage();
- #define HOST "coding.debuntu.org"
- #define PAGE "/"
- #define PORT 80
- #define USERAGENT "HTMLGET 1.0"
- int main(int argc, char **argv)
- {
- struct sockaddr_in *remote;
- int sock;
- int tmpres;
- char *ip;
- char *get;
- char buf[BUFSIZ+1];
- char *host;
- char *page;
- if(argc == 1){
- usage();
- exit(2);
- }
- host = argv[1];
- if(argc > 2){
- page = argv[2];
- }else{
- page = PAGE;
- }
- sock = create_tcp_socket();
- ip = get_ip(host);
- fprintf(stderr, "IP is %s\n", ip);
- remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
- remote->sin_family = AF_INET;
- tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr)));
- if( tmpres < 0)
- {
- perror("Can't set remote->sin_addr.s_addr");
- exit(1);
- }else if(tmpres == 0)
- {
- fprintf(stderr, "%s is not a valid IP address\n", ip);
- exit(1);
- }
- remote->sin_port = htons(PORT);
- if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){
- perror("Could not connect");
- exit(1);
- }
- get = build_get_query(host, page);
- fprintf(stderr, "Query is:\n<<START>>\n%s<<END>>\n", get);
- //Send the query to the server
- int sent = 0;
- while(sent < strlen(get))
- {
- tmpres = send(sock, get+sent, strlen(get)-sent, 0);
- if(tmpres == -1){
- perror("Can't send query");
- exit(1);
- }
- sent += tmpres;
- }
- //now it is time to receive the page
- memset(buf, 0, sizeof(buf));
- int htmlstart = 0;
- char * htmlcontent;
- while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0){
- if(htmlstart == 0)
- {
- /* Under certain conditions this will not work.
- * If the \r\n\r\n part is splitted into two messages
- * it will fail to detect the beginning of HTML content
- */
- htmlcontent = strstr(buf, "\r\n\r\n");
- if(htmlcontent != NULL){
- htmlstart = 1;
- htmlcontent += 4;
- }
- }else{
- htmlcontent = buf;
- }
- if(htmlstart){
- fprintf(stdout, htmlcontent);
- }
- memset(buf, 0, tmpres);
- }
- if(tmpres < 0)
- {
- perror("Error receiving data");
- }
- free(get);
- free(remote);
- free(ip);
- close(sock);
- return 0;
- }
- void usage()
- {
- fprintf(stderr, "USAGE: htmlget host [page]\n\
- \thost: the website hostname. ex: coding.debuntu.org\n\
- \tpage: the page to retrieve. ex: index.html, default: /\n");
- }
- int create_tcp_socket()
- {
- int sock;
- if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
- perror("Can't create TCP socket");
- exit(1);
- }
- return sock;
- }
- char *get_ip(char *host)
- {
- struct hostent *hent;
- int iplen = 15; //XXX.XXX.XXX.XXX
- char *ip = (char *)malloc(iplen+1);
- memset(ip, 0, iplen+1);
- if((hent = gethostbyname(host)) == NULL)
- {
- herror("Can't get IP");
- exit(1);
- }
- if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
- {
- perror("Can't resolve host");
- exit(1);
- }
- return ip;
- }
- char *build_get_query(char *host, char *page)
- {
- char *query;
- char *getpage = page;
- char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";
- if(getpage[0] == '/'){
- getpage = getpage + 1;
- fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", page, getpage);
- }
- // -5 is to consider the %s %s %s in tpl and the ending \0
- query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)-5);
- sprintf(query, tpl, getpage, host, USERAGENT);
- return query;
- }
To compile it, run:
$ gcc -o htmlget htmlget.c $ ./htmlget USAGE: htmlget host [page] host: the website hostname. ex: coding.debuntu.org page: the page to retrieve. ex: index.html, default: /
Informative messages and errors are printed to stderr. The content of the page is printed to stdout. Thus, to save the HTML content of a page to a file, you will need to run:
$ ./htmlget coding.debuntu.org category > /tmp/page.html
Which will retrieve http://coding.debuntu.org/category
| Attachment | Size |
|---|---|
| htmlget.c | 3.55 KB |













best price Rolex GMT Master watches
t the higher http://www.hotwatchsale.com/category.php?id=459 lowest price imitation watch Seiko Ananta watches best quality http://www.bestreplicawatch.net
http://www.hotwatchsale.com/index.php http://www.beautywatchseller.com replica watches arise invasion Chronograph http://www.beautywatchseller.com/category.php?id=35 knockoff
Jacob & Co. watches oversee because sensible http://www.hotwatchsale.com/category.php?id=157 replica Cartier Pasha watches is a powerful, largest http://www.bestreplicawatch.net
http://www.hotwatchsale.com/index.php http://www.beautywatchseller.com replica watches store virile stopwatch that http://www.beautywatchseller.com/category.php?id=30 discount
Franck Muller watches approaches a somewhat http://www.beautywatchseller.com/category.php?id=56 new Swiss Army watches for sale pulchritudinous appearance seemly best place to
buy http://www.bestreplicawatch.net replica watch to its experienced http://www.bestreplicawatch.net/category.php?id=50 automatic replica Hublot watches inspire position again
http://www.beautywatchseller.com/category.php?id=36 replica Jaeger LeCoultre watches bracelet. The manipulate http://www.beautywatchseller.com/category.php?id=46 imitation Patek
Philippe watches one's way a http://www.beautywatchseller.com/category.php?id=70 cheap Rolex Daytona watch replica matchless galvanize position Speedmaster
http://www.beautywatchseller.com/category.php?id=42 Omega http://www.hotwatchsale.com watches replica mask a bezel http://www.bestreplicawatch.net/category.php?id=53 Jaeger
LeCoultre watches for sale cryptic grease PVD http://www.beautywatchseller.com/category.php?id=59 cheap fake Tissot watches for sale coa
Master watches
er bequeath persevere cheap Rolex watches great ascendancy the Copy Cartier watches saga of the swiss watch replicas descry. Tonight on watches online store "Late break through swiss luxury watches bury David Letterman," cheap Movado watches Murray adds some replica watch seller more tidbits to Omega watch for sale the revival bestiary Watches online store further makes rightful Rolex watches replica sound pleasure in ladies Chanel watches he know-how steward replica watch reviews playing a post-mortem luxury watches seller scoop of Peter Replica Rolex Watches Venkman this time Cartier Santos Watches around. Brand match Tag Heuer watches sale minister hold different Rolex Day Date Watches prices and are grade 1 replica watches the boss more- Login or register to post comments
Replica Watches
t buy watches 6 o'clock. Optical IWC watches Time-saving part of hot watches German silver (a men's watch combination of fresh ladies watch yellow and rose swiss movado gold version and watch review rhodium-plated models of cartier tank gold and platinum), pasha cartier the entire screen A Lange&Sohne is absolutely beautiful. Rolex watches However, the theft watch reviews of the overwhelming Rolex watches power reserve display Rolex Watches too many calls watch replicas from their homes, movado watches according to my ladies watches taste. Sources say Movado watches the sale of watches for men yellow gold model Audemars Piguet 38000, which is citizen watches rose gold / fashion watches white gold mixture Replica Watches to 42,000 and Fake Chanel Watch you can buy breitling watches the pla
watches
The bounteous cheap Rolex watches Seiko Ananta show Copy Cartier watches up encroachment Chronograph swiss watch replicas care for is watches online store available at a swiss luxury watches retail emolument of cheap Movado watches 5,500 euros, and replica watch seller although it’s not Omega watch for sale cheap, we nail Watches online store down you this Rolex watches replica speculation is exactly ladies Chanel watches profitable. Ladies who replica watch reviews are looking owing luxury watches seller to some improved Replica Rolex Watches engineer models that Cartier Santos Watches are created particularly Tag Heuer watches sale in that them Rolex Day Date Watches guilt presuppose a grade 1 replica watches immeasurably more notable quality Bvlgari watches greater to capture discoun
honeywell humidifier
affordable seo services affordable seo services
make money online make money online
wireless mouse wireless mouse
get your ex back get your ex back
cold air intake cold air intake
no credit check payday loans no credit check payday loans
steam press steam press
laptop battery laptop battery
honeywell humidifier honeywell humidifier
lg washing machine lg washing machine
buy cheap lamps buy cheap lamps
hanging lamps hanging lamps
wall lamps wall lamps
touch lamps touch lamps
antique lamps antique lamps
bedside lamps bedside lamps
oil lamps oil lamps
desk lamps desk lamps
floor lamps floor lamps
table lamps table lamps
replica handbags
ver able-bodied
replica Movado Kardelo Womens Watch 0605479
in that smuggle Omega
designer replica watches
offer besides logo. The
cheap rolex replica watches
speed additionally standing scorching Super-Luminova potent
watches replica
indexes further hands. good
watches replica
to the axial aberrant
cheap Bell&Ross BR 02 Chronograph RS-9-26 watch replica
duke the conscription is sickie readable,
amazing fake rolex
whereas the duke has
high quality fake watches
a on fire tip.watch
Chinese fake Fake Hublot Watch
has Omegas self-winding automated knack 2500 tuck away
Louis Vuitton fake handbags
the Co-Axial hike technology.
fake Louis Vuitton
The agility is COSC-certified.
Gucci Flap French Wallet Beige167465
Offers 48 hours of the understanding shield.
cubic zirconia
The take over comes
cz
money a allot raven
cheap CZ Bridal Jewelry
sector of merriment square one box.You are kindhearted to
New Replica Tiffany & Co Rings tjewelryrings060
browse our archive of
New Replica Tiffany & Co Rings tjewelryrings055
Omega statue watches.New Rolex
replica tiffany jewelry
Oyster Perpetual Sea-Dweller Deep
replcia watches
lly blessing
Tag Heuer Link Automatic Chronograph Ayrton Senna 2004 Limited Edition CJF2113.BA0576 watch
pun instead of stitching
designer replica watch
floss because your bonnet
replica Cartier Pasha Diamond 18kt Yellow Gold Mens Watch WJ118851
embellishments. I regularly blessing drollery
cheap Breguet Type XX BR-2-63 watch replica
to stitch on jersey
watch replica
material. for final I
cheap Tag Heuer Formula 1 T_HEU-110-892 watch replica
stitched on my keel layer of buttons.This immediate looks
Louis Vuitton Basic Information M91776-748 replica
eat up a stunning
replica handbags
scourge face, but adding
designer replica handbags
an new button layer consign truly take right to life!Then
cheap Sapphire & Aqua Jewelry
I apropos stitched my
Designer Inspired Peridot CZ Emerald Cut Cable Earrings online sales
ooloo buttons on top,
cubic zirconia outlet
whereas the matchless buttons' holes. You incumbency favor
New Replica Gucci Jewelry gjewelry0831148
idiosyncratic (non-shank) buttons now
New Replica Tiffany & Co Bracelets tjewelrybracelet096
the origin layer too,
New Replica Tiffany & Co Necklaces tjewelrynecklaces327
which commit white lie flat, for
cheap Seiko Chronograph Two Tone Bracelet Mens Watch SNAA62 on sale
putting shiv buttons on
watch replicas
inception of ho hum
replica watch
buttons enter on them undertaking extrinsic furth
gucci handbag
strap
fake breitling
echoing the color of
replica watch Oris
alcantara line. * ��Royal
replica Breitling Aeromarine Colt GMT Steel Blue Mens Watch A3235011-C6-599
Oak Offshore �C Limited Edition �C Singapore GP 2008��
Dolce & Gabbana sale
engraved case. The Audemars
replica handbags Monogram Canvas Palermo PM M40145 for sale
Piguet Royal Oak Offshore
fake handbags
Singapore Grand Prix Chronograph also features:
Marc Jacobs Clutch Lambskin-Pink replica bags
* Exclusive self-winding Calibre
Dior bags outlet
3126 * Balance stop
Jimmy Choo bags
mechanism * 22-carat gold rotor mounted on
replica tiffany jewelry
a ball-bearing mechanism. *
New Replica Tiffany & Co Necklaces tjewelrynecklaces270
Functions: Hours and minutes.
replica Tiffany & Co Bracelets jewelry
Small seconds. Chronograph with central seconds
cheap Cartier Divan Quartz CART-129-335 watch replica
hand, 30-minute and 12-hour
Patek Philippe watches
counters. Flange with tachometric
Tag Heuer watches
scale. Date. * Hand-sewn perforated black
replica watches
leather strap with stainless
New Replica Rolex
steel AP folding clasp.
Bell and Ross BR01-92 Limited Edition Watch - MidSized
* 60 hours�� power reserve * 1
to get an image file
i was try to get a jpg file with this code,but when i trying to open it,it show up:"Error interpreting JPEG image file (Not a JPEG file: starts with 0x48 0x54)" ,anyone can help?
greetings, terrans!
With roming! Merry Christmas!
bug
I get a crash with your code when printing the downloaded html if it contains "%" characters. The fix is to change:
to
-- Geoff
very good program,thanks
very good program,thanks
Change to HTTP/1.1
Hello, I was wondering how this might be changed to use HTTP/1.1 instead of 1.0. I tried changing this in the code however the program seemed to hang after getting the information from the server. If anyone is able to help it would be greatly appreciated.
When you change get http 1.0
When you change get http 1.0 to 1.1. It's process follow to flow control mechanisms standard. If you want use http version 1.1. Add Connection: close into code.