c - How does this code from "Network programming" examples work? -
i reading beej's "guide network programming".
in 1 of intro examples talks getting ip address hostname (like google.com or yahoo.com instance). here code.
/* ** showip.c -- show ip addresses host given on command line */ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { struct addrinfo hints, *res, *p; int status; char ipstr[inet6_addrstrlen]; if (argc != 2) { fprintf(stderr,"usage: showip hostname\n"); return 1; } memset(&hints, 0, sizeof hints); hints.ai_family = af_unspec; // af_inet or af_inet6 force version hints.ai_socktype = sock_stream; if ((status = getaddrinfo(argv[1], null, &hints, &res)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); return 2; } printf("ip addresses %s:\n\n", argv[1]); for(p = res; p != null; p = p->ai_next) { void *addr; char *ipver; // pointer address itself, // different fields in ipv4 , ipv6: if (p->ai_family == af_inet) { // ipv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); ipver = "ipv4"; } else { // ipv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); ipver = "ipv6"; } // convert ip string , print it: inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); printf(" %s: %s\n", ipver, ipstr); } freeaddrinfo(res); // free linked list return 0; } the part confuses me loop.
for(p = res; p != null; p = p->ai_next) { void *addr; char *ipver; // pointer address itself, // different fields in ipv4 , ipv6: if (p->ai_family == af_inet) { // ipv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); ipver = "ipv4"; } else { // ipv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); ipver = "ipv6"; } // convert ip string , print it: inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); printf(" %s: %s\n", ipver, ipstr); } would mind going through psuedo-step-by-step @ whats going on or these things are? iterating through linked list?.. have general idea of struct addrinfo heck struct *res , struct *p or void *addr , *char ipversion.
first thing's first, know linked list is? if understand that, you'll recognise loop going. p pointer structure references (links) next structure in list. you're looping through list of structures, addrinfo structs. 4
now, thing need know network packets they're made of header. ethernet frame. hardware hardware protocol. let's things around on physical, bounded network knows nothing routing across physical network boundaries.
next comes tcp or possibly transport layer protocol, sits somewhere inbetween 2 levels. tcp versus udp versus x how manage packets - example tcp requires packets reassembled in order, whereas udp "broadcast"-type protocol.
finally, have internet protocol suite (ipv4, ipv6). these higher level protocols control broader sense of routing, know internet @ large, less steps needed there.
a great explanation of handy diagram on page. complete picture, bgp how routers know how move stuff around.
tcp/udp fit picture being part of (enscapulated in) protocol in question (ipv4 example)
so ethernet frames contain other protocols notably ipv4, contain information routers need out across internet (across multiple physical networks). internet protocol specifies want go, are. typical's ipv4 body remains unchanged across whole transit, every time traverses physical networks gets wrapped in different ethernet packet.
now, in ethernet header there field finding out "ethernet body" contains. line:
if (p->ai_family == af_inet) { does. af_inet constant matches value tcp uses identify packet body ipv4. so, if you're looking @ ipv4 header, loop goes on read information.
the else clause technically wrong, because not being ipv4 doesn't automatically make ipv6. change test ipv6 this:
else if (p->ai_family == af_inet6) { which might want do, in case pick else.
now it's worth explaining bit of magic:
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; this takes network, or raw, form of data appears sequence of bytes, , casts (coverts it) fields in struct. because know how big fields going be, quick , easy way extract out need.
the last thing needs explanation this:
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); there other ways of achieving this, ntohs().
basically network data transmitted in big endian encoding, , in order read it, need (potentially) convert data encoding of system. big endian, or little, depends on system part. have read of wikipedia article on endianness.
summary: you're looking @ here combination of computer science structures, how networks work , c code.
Comments
Post a Comment