0 Bewertungen0% fanden dieses Dokument nützlich (0 Abstimmungen)
34 Ansichten32 Seiten
Beej's Guide to Network Programming using Internet Sockets Platform and compiler. Most of the code contained within this document was compiled on a Linux PC using Gnu's gcc compiler.
Beej's Guide to Network Programming using Internet Sockets Platform and compiler. Most of the code contained within this document was compiled on a Linux PC using Gnu's gcc compiler.
Beej's Guide to Network Programming using Internet Sockets Platform and compiler. Most of the code contained within this document was compiled on a Linux PC using Gnu's gcc compiler.
Platform and Compiler Most of the code contained within this document was compiled on a Linux PC using Gnu's gcc compiler. It was also found to compile on HPUX using gcc. ote that e!er" code snippet was not indi!iduall" tested. Contents# $hat is a soc%et& 'wo '"pes of Internet (oc%ets Low le!el onsense and etwor% 'heor" structs))*now these+ or aliens will destro" the planet, Con!ert the ati!es, IP -ddresses and How to .eal $ith 'hem soc%et/0))Get the 1ile .escriptor, 2ind/0))$hat port am I on& connect/0))He"+ "ou, listen/0))$ill some2od" please call me& accept/0))3'han% "ou for calling port 4567.3 send/0 and rec!/0))'al% to me+ 2a2", sendto/0 and rec!from/0))'al% to me+ .G8-M)st"le close/0 and shutdown/0))Get outta m" face, getpeername/0))$ho are "ou& gethostname/0))$ho am I& .())9ou sa" 3whitehouse.go!3+ I sa" 3:6;.:4<.=57.:773 Client)(er!er >ac%ground - (imple (tream (er!er - (imple (tream Client .atagram (oc%ets >loc%ing select/0))("nchronous I?@ Multiplexing. Cool, More references .isclaimer and Call for Help : $hat is a soc%et& A!er"thing in Unix is a file, $hat that person ma" ha!e 2een tal%ing a2out is the fact that when Unix programs do an" sort of I?@+ the" do it 2" reading or writing to a file descriptor. - file descriptor is simpl" an integer associated with an open file. >ut /and here's the catch0+ that file can 2e a networ% connection+ a 1I1@+ a pipe+ a terminal+ a real on)the)dis% file+ or Bust a2out an"thing else. A!er"thing in Unix is a file, (o when "ou want to communicate with another program o!er the Internet "ou're gonna do it through a file descriptor+ "ou'd 2etter 2elie!e it. 3$here do I get this file descriptor for networ% communication+ Mr. (mart")Pants&3 is pro2a2l" the last Cuestion on "our mind right now+ 2ut I'm going to answer it an"wa"# 9ou ma%e a call to the soc%et/0 s"stem routine. It returns the soc%et descriptor+ and "ou communicate through it using the specialiDed send/0 and rec!/0 /3man send3+ 3man rec!30 soc%et calls. If it's a file descriptor+ wh" in the hell can't I Bust use the normal read/0 and write/0 calls to communicate through the soc%et&3 'he short answer is+ 39ou can,3 'he longer answer is+ 39ou can+ 2ut send/0 and rec!/0 offer much greater control o!er "our data transmission.3 'here are all %inds of soc%ets. 'here are .-8P- Internet addresses /Internet (oc%ets0+ path names on a local node /Unix (oc%ets0+ CCI'' X.=E addresses /X.=E (oc%ets that "ou can safel" ignore0+ and pro2a2l" man" others depending on which Unix fla!or "ou run. 'his document deals onl" with the first# Internet (oc%ets. 'wo '"pes of Internet (oc%ets I'm onl" going to tal% a2out two t"pes here. Axcept for this sentence+ where I'm going to tell "ou that 38aw (oc%ets3 are also !er" powerful and "ou should loo% them up. $hat are the two t"pes& @ne is 3(tream (oc%ets3F the other is 3.atagram (oc%ets3+ which ma" hereafter 2e referred to as 3(@C*G('8A-M3 and 3(@C*G.G8-M3+ respecti!el". .atagram soc%ets are sometimes called 3connectionless soc%ets3 /though the" can 2e connect/0'd if "ou reall" want. (ee connect/0+ 2elow. = (tream soc%ets are relia2le two)wa" connected communication streams. If "ou output two items into the soc%et in the order 3:+ =3+ the" will arri!e in the order 3:+ =3 at the opposite end. 'he" will also 2e error free. -n" errors "ou do encounter are figments of "our own deranged mind+ and are not to 2e discussed here. $hat uses stream soc%ets& $ell+ "ou ma" ha!e heard of the telnet application+ "es& It uses stream soc%ets. -ll the characters "ou t"pe need to arri!e in the same order "ou t"pe them+ right& -lso+ $$$ 2rowsers use the H''P protocol which uses stream soc%ets to get pages. Indeed+ if "ou telnet to a $$$ site on port ;7+ and t"pe 3GA' pagename3+ it'll dump the H'ML 2ac% at "ou, (tream soc%ets achie!e this high le!el of data transmission Cualit" 2" using protocol called 3'he 'ransmission Control Protocol3+ otherwise %nown as 3'CP3 . 'CP ma%es sure "our data arri!es seCuentiall" and error)free. 9ou ma" ha!e heard 3'CP3 2efore as the 2etter half of 3'CP?IP3 where 3IP3 stands for 3Internet Protocol3/ IP deals with Internet routing onl".0 $hat a2out .atagram soc%ets& $h" are the" called connectionless& $hat is the deal+ here+ an"wa"& $h" are the" unrelia2le& $ell+ here are some facts# if "ou send a datagram+ it ma" arri!e. It ma" arri!e out of order. If it arri!es+ the data within the pac%et will 2e error)free. .atagram soc%ets also use IP for routing+ 2ut the" don't use 'CPF the" use the 3User .atagram Protocol3+ or 3U.P3 $h" are the" connectionless& $ell+ 2asicall"+ it's 2ecause "ou don't ha!e to maintain an open connection as "ou do with stream soc%ets. 9ou Bust 2uild a pac%et+ slap an IP header on it with destination information+ and send it out. o connection needed. 'he" are generall" used for pac%et)2")pac%et transfers of information. (ample applications# tftp+ 2ootp+ etc. How do these programs e!en wor% if datagrams might get lost&,3 $ell+ m" human friend+ each has it's own protocol on top of U.P. 1or example+ the tftp protocol sa"s that for each pac%et that gets sent+ the recipient has to send 2ac% a pac%et that sa"s+ 3I got it,3 /an 3-C*3 pac%et.0 If the sender of the original pac%et gets no repl" in+ sa"+ fi!e seconds+ he'll re)transmit the pac%et until he finall" gets an -C*. 'his ac%nowledgment procedure is !er" important when implementing (@C*G.G8-M applications. Low le!el onsense and etwor% 'heor" 4 (ince I Bust mentioned la"ering of protocols+ it's time to tal% a2out how networ%s reall" wor%+ and to show some examples of how (@C*G.G8-M pac%ets are 2uilt. Practicall"+ "ou can pro2a2l" s%ip this section. It's good 2ac%ground+ howe!er. He"+ %ids+ it's time to learn a2out .ata Ancapsulation, 'his is !er" !er" important. It's so important that "ou might Bust learn a2out it if "ou ta%e the networ%s course here at Chico (tate F)0. >asicall"+ it sa"s this# a pac%et is 2orn+ the pac%et is wrapped /3encapsulated30 in a header /and ma"2e footer0 2" the first protocol /sa"+ the '1'P protocol0+ then the whole thing /'1'P header included0 is encapsulated again 2" the next protocol /sa"+ U.P0+ then again 2" the next /IP0+ then again 2" the final protocol on the hardware /ph"sical0 la"er /sa"+ Athernet0. $hen another computer recei!es the pac%et+ the hardware strips the Athernet header+ the %ernel strips the IP and U.P headers+ the '1'P program strips the '1'P header+ and it finall" has the data. ow I can finall" tal% a2out the infamous La"ered etwor% Model. 'his etwor% Model descri2es a s"stem of networ% functionalit" that has man" ad!antages o!er other models. 1or instance+ "ou can write soc%ets programs that are exactl" the same without caring how the data is ph"sicall" transmitted /serial+ thin Athernet+ -UI+ whate!er0 2ecause programs on lower le!els deal with it for "ou. 'he actual networ% hardware and topolog" is transparent to the soc%et programmer. $ithout an" further ado+ I'll present the la"ers of the full)2lown model. 8emem2er this for networ% class exams# -pplication Presentation (ession 'ransport etwor% .ata Lin% Ph"sical 'he Ph"sical La"er is the hardware /serial+ Athernet+ etc.0. 'he -pplication La"er is Bust a2out as far from the ph"sical la"er as "ou can imagine))it's the place where users interact with the networ%. ow+ this model is so general "ou could pro2a2l" use it as an automo2ile repair guide if "ou reall" wanted to. - la"ered model more consistent with Unix might 2e# 5 -pplication La"er /telnet+ ftp+ etc.0 Host)to)Host 'ransport La"er /'CP+ U.P0 Internet La"er /IP and routing0 etwor% -ccess La"er /was etwor%+ .ata Lin%+ and Ph"sical0 -t this point in time+ "ou can pro2a2l" see how these la"ers correspond to the encapsulation of the original data. (ee how much wor% there is in 2uilding a simple pac%et& HeeD, -nd "ou ha!e to t"pe in the pac%et headers "ourself using 3cat3, Hust %idding. -ll "ou ha!e to do for stream soc%ets is send/0 the data out. -ll "ou ha!e to do for datagram soc%ets is encapsulate the pac%et in the method of "our choosing and sendto/0 it out. 'he %ernel 2uilds the 'ransport La"er and Internet La"er on for "ou and the hardware does the etwor% -ccess La"er. -h+ modern technolog". (o ends our 2rief fora" into networ% theor". @h "es+ I forgot to tell "ou e!er"thing I wanted to sa" a2out routing# nothing, 'hat's right+ I'm not going to tal% a2out it at all. 'he router strips the pac%et to the IP header+ consults its routing ta2le+ 2lah 2lah 2lah. Chec% out the IP 81C if "ou reall" reall" care. If "ou ne!er learn a2out it+ well+ "ou'll li!e. structs $ell+ we're finall" here. It's time to tal% a2out programming. In this section+ I'll co!er !arious data t"pes used 2" the soc%ets interface+ since some of them are a real 2itch to figure out. 1irst the eas" one# a soc%et descriptor. - soc%et descriptor is the following t"pe# int Hust a regular int. 'hings get weird from here+ so Bust read through and 2ear with me. *now this# there are two 2"te orderings# most significant 2"te /sometimes called an 3octet30 first+ or least significant 2"te first. 'he former is called 3etwor% >"te @rder3. (ome machines store their num2ers internall" in etwor% >"te @rder+ some don't. $hen I sa" something has to 2e in >@+ "ou ha!e to call a function /such as htons/00 to change it from 3Host >"te @rder3. If I don't sa" 3>@3+ then "ou must lea!e the !alue in Host >"te @rder. E M" 1irst (truct/'M0))struct soc%addr. 'his structure holds soc%et address information for man" t"pes of soc%ets# struct soc%addr I unsigned short saGfamil"F ?J address famil"+ -1Gxxx J? char saGdataK:5LF ?J :5 2"tes of protocol address J? MF saGfamil" can 2e a !ariet" of things+ 2ut it'll 2e 3-1GIA'3 for e!er"thing we do in this document. saGdata contains a destination address and port num2er for the soc%et. 'his is rather unwield". 'o deal with struct soc%addr+ programmers created a parallel structure# struct soc%addrGin /3in3 for 3Internet3.0 struct soc%addrGin I short int sinGfamil"F ?J -ddress famil" J? unsigned short int sinGportF ?J Port num2er J? struct inGaddr sinGaddrF ?J Internet address J? unsigned char sinGDeroK;LF ?J (ame siDe as struct soc%addr J? MF 'his structure ma%es it eas" to reference elements of the soc%et address. ote that sinGDero /which is included to pad the structure to the length of a struct soc%addr0 should 2e set to all Deros with the function 2Dero/0 or memset/0. -lso+ and this is the important 2it+ a pointer to a struct soc%addrGin can 2e cast to a pointer to a struct soc%addr and !ice) !ersa. (o e!en though soc%et/0 wants a struct soc%addr J+ "ou can still use a struct soc%addrGin and cast it at the last minute, -lso+ notice that sinGfamil" corresponds to saGfamil" in a struct soc%addr and should 2e set to 3-1GIA'3. 1inall"+ the sinGport and sinGaddr must 2e in etwor% >"te @rder, 3>ut+3 "ou o2Bect+ 3how can the entire structure+ struct inGaddr sinGaddr+ 2e in etwor% >"te @rder&3 'his Cuestion reCuires careful examination of the structure struct inGaddr+ one of the worst unions ali!e# ?J Internet address /a structure for historical reasons0 J? struct inGaddr I unsigned long sGaddrF MF $ell+ it used to 2e a union+ 2ut now those da"s seem to 2e gone. Good riddance. (o if "ou ha!e declared 3ina3 to 2e of t"pe struct soc%addrGin+ then 3ina.sinGaddr.sGaddr3 references the 5 2"te IP address /in etwor% >"te @rder0. ote that e!en if "our s"stem still uses the God)awful union for struct inGaddr+ "ou can still reference the 5 2"te IP address in exactl" the same wa" as I did a2o!e /this due to Ndefines.0 O Con!ert the ati!es, $e'!e now 2een lead right into the next section. 'here's 2een too much tal% a2out this etwor% to Host >"te @rder con!ersion))now is the time for action, -ll right". 'here are two t"pes that "ou can con!ert# short /two 2"tes0 and long /four 2"tes0. 'hese functions wor% for the unsigned !ariations as well. (a" "ou want to con!ert a short from Host >"te @rder to etwor% >"te @rder. (tart with 3h3 for 3host3+ follow it with 3to3+ then 3n3 for 3networ%3+ and 3s3 for 3short3# h)to)n)s+ or htons/0 /read# 3Host to etwor% (hort30. It's almost too eas"... 9ou can use e!er" com2ination if 3n3+ 3h3+ 3s3+ and 3l3 "ou want+ not counting the reall" stupid ones. 1or example+ there is @' a stolh/0 /3(hort to Long Host30 function))not at this part"+ an"wa". >ut there are# htons/0))3Host to etwor% (hort3 htonl/0))3Host to etwor% Long3 ntohs/0))3etwor% to Host (hort3 ntohl/0))3etwor% to Host Long3 ow+ "ou ma" thin% "ou're wising up to this. 9ou might thin%+ 3$hat do I do if I ha!e to change 2"te order on a char&3 'hen "ou might thin%+ 3Uh+ ne!er mind.3 9ou might also thin% that since "our O;777 machine alread" uses networ% 2"te order+ "ou don't ha!e to call htonl/0 on "our IP addresses. 9ou would 2e right+ >U' if "ou tr" to port to a machine that has re!erse networ% 2"te order+ "our program will fail. >e porta2le, 'his is a Unix world, 8emem2er# put "our 2"tes in etwor% @rder 2efore "ou put them on the networ%. - final point# wh" do sinGaddr and sinGport need to 2e in etwor% >"te @rder in a struct soc%addrGin+ 2ut sinGfamil" does not& 'he answer# sinGaddr and sinGport get encapsulated in the pac%et at the IP and U.P la"ers+ respecti!el". 'hus+ the" must 2e in etwor% >"te @rder. Howe!er+ the sinGfamil" field is onl" used 2" the %ernel to determine what t"pe of address the structure contains+ so it must 2e in Host >"te @rder. -lso+ since sinGfamil" does not get sent out on the networ%+ it can 2e in Host >"te @rder. IP -ddresses and How to .eal $ith 'hem < 1ortunatel" for "ou+ there are a 2unch of functions that allow "ou to manipulate IP addresses. o need to figure them out 2" hand and stuff them in a long with the PP operator. 1irst+ let's sa" "ou ha!e a struct soc%addrGin ina+ and "ou ha!e an IP address 3:4=.=5:.E.:73 that "ou want to store into it. 'he function "ou want to use+ inetGaddr/0+ con!erts an IP address in num2ers)and)dots notation into an unsigned long. 'he assignment can 2e made as follows# ina.sinGaddr.sGaddr Q inetGaddr/3:4=.=5:.E.:730F otice that inetGaddr/0 returns the address in etwor% >"te @rder alread"))"ou don't ha!e to call htonl/0. (well, ow+ the a2o!e code snippet isn't !er" ro2ust 2ecause there is no error chec%ing. (ee+ inetGaddr/0 returns ): on error. 8emem2er 2inar" num2ers& /unsigned0): Bust happens to correspond to the IP address =EE.=EE.=EE.=EE, 'hat's the 2roadcast address, $rongo. 8emem2er to do "our error chec%ing properl". -ll right+ now "ou can con!ert string IP addresses to longs. $hat a2out the other wa" around& $hat if "ou ha!e a struct inGaddr and "ou want to print it in num2ers)and)dots notation& In this case+ "ou'll want to use the function inetGntoa/0 /3ntoa3 means 3networ% to ascii30 li%e this# printf/3Rs3+inetGntoa/ina.sinGaddr00F 'hat will print the IP address. ote that inetGntoa/0 ta%es a struct inGaddr as an argument+ not a long. -lso notice that it returns a pointer to a char. 'his points to a staticall" stored char arra" within inetGntoa/0 so that each time "ou call inetGntoa/0 it will o!erwrite the last IP address "ou as%ed for. 1or example# char Ja:+ Ja=F . . a: Q inetGntoa/ina:.sinGaddr0F ?J this is :6;.6=.:=6.: J? a= Q inetGntoa/ina=.sinGaddr0F ?J this is :4=.=5:.E.:7 J? printf/3address :# RsSn3+a:0F printf/3address =# RsSn3+a=0F will print# address :# :4=.=5:.E.:7 address =# :4=.=5:.E.:7 If "ou need to sa!e the address+ strcp"/0 it to "our own character arra". 'hat's all on this topic for now. Later+ "ou'll learn to con!ert a string li%e 3whitehouse.go!3 into its corresponding IP address /see .(+ 2elow.0 ; soc%et/0))Get the 1ile .escriptor, I guess I can put it off no longer))I ha!e to tal% a2out the soc%et/0 s"stem call. Here's the 2rea%down# Ninclude Ps"s?t"pes.hT Ninclude Ps"s?soc%et.hT int soc%et/int domain+ int t"pe+ int protocol0F >ut what are these arguments& 1irst+ domain should 2e set to 3-1GIA'3+ Bust li%e in the struct soc%addrGin /a2o!e.0 ext+ the t"pe argument tells the %ernel what %ind of soc%et this is# (@C*G('8A-M or (@C*G.G8-M. 1inall"+ Bust set protocol to 373. /otes# there are man" more domains than I'!e listed. 'here are man" more t"pes than I'!e listed. (ee the soc%et/0 man page. -lso+ there's a 32etter3 wa" to get the protocol. (ee the getproto2"name/0 man page.0 soc%et/0 simpl" returns to "ou a soc%et descriptor that "ou can use in later s"stem calls+ or ): on error. 'he glo2al !aria2le errno is set to the error's !alue /see the perror/0 man page.0 2ind/0))$hat port am I on& @nce "ou ha!e a soc%et+ "ou might ha!e to associate that soc%et with a port on "our local machine. /'his is commonl" done if "ou're going to listen/0 for incoming connections on a specific port))MU.s do this when the" tell "ou to 3telnet to x.".D port O6O63.0 If "ou're going to onl" 2e doing a connect/0+ this ma" 2e unnecessar". 8ead it an"wa"+ Bust for %ic%s. Here is the s"nopsis for the 2ind/0 s"stem call# Ninclude Ps"s?t"pes.hT Ninclude Ps"s?soc%et.hT int 2ind/int soc%fd+ struct soc%addr Jm"Gaddr+ int addrlen0F soc%fd is the soc%et file descriptor returned 2" soc%et/0. m"Gaddr is a pointer to a struct soc%addr that contains information a2out "our address+ namel"+ port and IP address. addrlen can 2e set to siDeof/struct soc%addr0. $hew. 'hat's a 2it to a2sor2 in one chun%. Let's ha!e an example# 6 Ninclude Pstring.hT Ninclude Ps"s?t"pes.hT Ninclude Ps"s?soc%et.hT Ndefine M9P@8' 4567 main/0 I int soc%fdF struct soc%addrGin m"GaddrF soc%fd Q soc%et/-1GIA'+ (@C*G('8A-M+ 70F ?J do some error chec%ing, J? m"Gaddr.sinGfamil" Q -1GIA'F ?J host 2"te order J? m"Gaddr.sinGport Q htons/M9P@8'0F ?J short+ networ% 2"te order J? m"Gaddr.sinGaddr.sGaddr Q inetGaddr/3:4=.=5:.E.:730F 2Dero/U/m"Gaddr.sinGDero0+ ;0F ?J Dero the rest of the struct J? ?J don't forget "our error chec%ing for 2ind/0# J? 2ind/soc%fd+ /struct soc%addr J0Um"Gaddr+ siDeof/struct soc%addr00F . . . 'here are a few things to notice here. m"Gaddr.sinGport is in etwor% >"te @rder. (o is m"Gaddr.sinGaddr.sGaddr. -nother thing to watch out for is that the header files might differ from s"stem to s"stem. 'o 2e sure+ "ou should chec% "our local man pages. Lastl"+ on the topic of 2ind/0+ I should mention that some of the process of getting "our own IP address and?or port can can 2e automated# m"Gaddr.sinGport Q 7F ?J choose an unused port at random J? m"Gaddr.sinGaddr.sGaddr Q I-..8G-9F ?J use m" IP address J? (ee+ 2" setting m"Gaddr.sinGport to Dero+ "ou are telling 2ind/0 to choose the port for "ou. Li%ewise+ 2" setting m"Gaddr.sinGaddr.sGaddr to I-..8G-9+ "ou are telling it to automaticall" fill in the IP address of the machine the process is running on. If "ou are into noticing little things+ "ou might ha!e seen that I didn't put I-..8G-9 into etwor% >"te @rder, aught" me. Howe!er+ I ha!e inside info# I-..8G-9 is reall" Dero, Vero still has Dero on 2its e!en if "ou rearrange the 2"tes. Howe!er+ purists will point out that there could 2e a parallel dimension where I-..8G-9 is+ sa"+ := and that m" code won't wor% there. 'hat's o% with me# m"Gaddr.sinGport Q htons/70F ?J choose an unused port at random J? :7 m"Gaddr.sinGaddr.sGaddr Q htonl/I-..8G-90F ?J use m" IP address J? ow we're so porta2le "ou pro2a2l" wouldn't 2elie!e it. I Bust wanted to point that out+ since most of the code "ou come across won't 2other running I-..8G-9 through htonl/0. 2ind/0 also returns ): on error and sets errno to the error's !alue. -nother thing to watch out for when calling 2ind/0# don't go under2oard with "our port num2ers. -ll ports 2elow :7=5 are 8A(A8WA., 9ou can ha!e an" port num2er a2o!e that+ right up to OEE4E /pro!ided the" aren't alread" 2eing used 2" another program.0 @ne small extra final note a2out 2ind/0# there are times when "ou won't a2solutel" ha!e to call it. If "ou are connect/0'ing to a remote machine and "ou don't care what "our local port is /as is the case with telnet0+ "ou can simpl" call connect/0+ it'll chec% to see if the soc%et is un2ound+ and will 2ind/0 it to an unused local port. connect/0))He"+ "ou, Let's Bust pretend for a few minutes that "ou're a telnet application. 9our user commands "ou /Bust li%e in the mo!ie '8@0 to get a soc%et file descriptor. 9ou compl" and call soc%et/0. ext+ the user tells "ou to connect to 3:4=.=5:.E.:73 on port 3=43 /the standard telnet port.0 @h m" God, $hat do "ou do now& Luc%" for "ou+ program+ "ou're now perusing the section on connect/0))how to connect to a remote host. 9ou read furiousl" onward+ not wanting to disappoint "our user... 'he connect/0 call is as follows# Ninclude Ps"s?t"pes.hT Ninclude Ps"s?soc%et.hT int connect/int soc%fd+ struct soc%addr Jser!Gaddr+ int addrlen0F soc%fd is our friendl" neigh2orhood soc%et file descriptor+ as returned 2" the soc%et/0 call+ ser!Gaddr is a struct soc%addr containing the destination port and IP address+ and addrlen can 2e set to siDeof/struct soc%addr0. Isn't this starting to ma%e more sense& Let's ha!e an example# Ninclude Pstring.hT Ninclude Ps"s?t"pes.hT :: Ninclude Ps"s?soc%et.hT Ndefine .A('GIP 3:4=.=5:.E.:73 Ndefine .A('GP@8' =4 main/0 I int soc%fdF struct soc%addrGin destGaddrF ?J will hold the destination addr J? soc%fd Q soc%et/-1GIA'+ (@C*G('8A-M+ 70F ?J do some error chec%ing, J? destGaddr.sinGfamil" Q -1GIA'F ?J host 2"te order J? destGaddr.sinGport Q htons/.A('GP@8'0F ?J short+ networ% 2"te order J? destGaddr.sinGaddr.sGaddr Q inetGaddr/.A('GIP0F 2Dero/U/destGaddr.sinGDero0+ ;0F ?J Dero the rest of the struct J? ?J don't forget to error chec% the connect/0, J? connect/soc%fd+ /struct soc%addr J0UdestGaddr+ siDeof/struct soc%addr00F . . . -gain+ 2e sure to chec% the return !alue from connect/0))it'll return ): on error and set the !aria2le errno. -lso+ notice that we didn't call 2ind/0. >asicall"+ we don't care a2out our local port num2erF we onl" care where we're going. 'he %ernel will choose a local port for us+ and the site we connect to will automaticall" get this information from us. o worries. listen/0))$ill some2od" please call me& @%+ time for a change of pace. $hat if "ou don't want to connect to a remote host. (a"+ Bust for %ic%s+ that "ou want to wait for incoming connections and handle them in some wa". 'he process is two step# first "ou listen/0+ then "ou accept/0 /see 2elow.0 'he listen call is fairl" simple+ 2ut reCuires a 2it of explanation# int listen/int soc%fd+ int 2ac%log0F := soc%fd is the usual soc%et file descriptor from the soc%et/0 s"stem call. 2ac%log is the num2er of connections allowed on the incoming Cueue. $hat does that mean& $ell+ incoming connections are going to wait in this Cueue until "ou accept/0 them /see 2elow0 and this is the limit on how man" can Cueue up. Most s"stems silentl" limit this num2er to a2out =7F "ou can pro2a2l" get awa" with setting it to E or :7. -gain+ as per usual+ listen/0 returns ): and sets errno on error. $ell+ as "ou can pro2a2l" imagine+ we need to call 2ind/0 2efore we call listen/0 or the %ernel will ha!e us listening on a random port. >leah, (o if "ou're going to 2e listening for incoming connections+ the seCuence of s"stem calls "ou'll ma%e is# soc%et/0F 2ind/0F listen/0F ?J accept/0 goes here J? I'll Bust lea!e that in the place of sample code+ since it's fairl" self)explanator". /'he code in the accept/0 section+ 2elow+ is more complete.0 'he reall" tric%" part of this whole sha)2ang is the call to accept/0. accept/0))3'han% "ou for calling port 4567.3 Get read"))the accept/0 call is %inda weird, $hat's going to happen is this# someone far far awa" will tr" to connect/0 to "our machine on a port that "ou are listen/0'ing on. 'heir connection will 2e Cueued up waiting to 2e accept/0'ed. 9ou call accept/0 and "ou tell it to get the pending connection. It'll return to "ou a 2rand new soc%et file descriptor to use for this single connection, 'hat's right+ suddenl" "ou ha!e two soc%et file descriptors for the price of one, 'he original one is still listening on "our port and the newl" created one is finall" read" to send/0 and rec!/0. $e're there, 'he call is as follows# Ninclude Ps"s?soc%et.hT int accept/int soc%fd+ !oid Jaddr+ int Jaddrlen0F soc%fd is the listen/0'ing soc%et descriptor. Aas" enough. addr will usuall" 2e a pointer to a local struct soc%addrGin. 'his is where the information a2out the incoming connection will go /and "ou can determine which host is calling "ou from which port0. addrlen is a local integer !aria2le that should 2e set to siDeof/struct soc%addrGin0 2efore its address is passed to accept/0. -ccept will not put more than that man" 2"tes into addr. If it puts fewer in+ it'll change the !alue of addrlen to reflect that. :4 Guess what& accept/0 returns ): and sets errno if an error occurs. >etcha didn't figure that. Li%e 2efore+ this is a 2unch to a2sor2 in one chun%+ so here's a sample code fragment for "our perusal# Ninclude Pstring.hT Ninclude Ps"s?t"pes.hT Ninclude Ps"s?soc%et.hT Ndefine M9P@8' 4567 ?J the port users will 2e connecting to J? Ndefine >-C*L@G :7 ?J how man" pending connections Cueue will hold J? main/0 I int soc%fd+ newGfdF ?J listen on soc%Gfd+ new connection on newGfd J? struct soc%addrGin m"GaddrF ?J m" address information J? struct soc%addrGin theirGaddrF ?J connector's address information J? int sinGsiDeF soc%fd Q soc%et/-1GIA'+ (@C*G('8A-M+ 70F ?J do some error chec%ing, J? m"Gaddr.sinGfamil" Q -1GIA'F ?J host 2"te order J? m"Gaddr.sinGport Q htons/M9P@8'0F ?J short+ networ% 2"te order J? m"Gaddr.sinGaddr.sGaddr Q I-..8G-9F ?J auto)fill with m" IP J? 2Dero/U/m"Gaddr.sinGDero0+ ;0F ?J Dero the rest of the struct J? ?J don't forget "our error chec%ing for these calls# J? 2ind/soc%fd+ /struct soc%addr J0Um"Gaddr+ siDeof/struct soc%addr00F listen/soc%fd+ >-C*L@G0F sinGsiDe Q siDeof/struct soc%addrGin0F newGfd Q accept/soc%fd+ UtheirGaddr+ UsinGsiDe0F . . . -gain+ note that we will use the soc%et descriptor newGfd for all send/0 and rec!/0 calls. If "ou're onl" getting one single connection e!er+ "ou can close/0 the original soc%fd in order to pre!ent more incoming connections on the same port+ if "ou so desire. :5 send/0 and rec!/0))'al% to me+ 2a2", 'hese two functions are for communicating o!er stream soc%ets or connected datagram soc%ets. If "ou want to use regular unconnected datagram soc%ets+ "ou'll need to see the section on sendto/0 and rec!from/0+ 2elow. 'he send/0 call# int send/int soc%fd+ const !oid Jmsg+ int len+ int flags0F soc%fd is the soc%et descriptor "ou want to send data to /whether it's the one returned 2" soc%et/0 or the one "ou got with accept/0.0 msg is a pointer to the data "ou want to send+ and len is the length of that data in 2"tes. Hust set flags to 7. /(ee the send/0 man page for more information concerning flags.0 (ome sample code might 2e# char Jmsg Q 3>eeB was here,3F int len+ 2"tesGsentF . . len Q strlen/msg0F 2"tesGsent Q send/soc%fd+ msg+ len+ 70F . . . send/0 returns the num2er of 2"tes actuall" sent out))this might 2e less than the num2er "ou told it to send, (ee+ sometimes "ou tell it to send a whole go2 of data and it Bust can't handle it. It'll fire off as much of the data as it can+ and trust "ou to send the rest later. 8emem2er+ if the !alue returned 2" send/0 doesn't match doesn't match the !alue in len+ it's up to "ou to send the rest of the string. 'he good news is this# if the pac%et is small /less than :* or so0 it will pro2a2l" manage to send the whole thing all in one go. -gain+ ): is returned on error+ and errno is set to the error num2er. 'he rec!/0 call is similar in man" respects# int rec!/int soc%fd+ !oid J2uf+ int len+ unsigned int flags0F soc%fd is the soc%et descriptor to read from+ 2uf is the 2uffer to read the information into+ len is the maximum length of the 2uffer+ and flags can again 2e set to 7. /(ee the rec!/0 man page for flag information.0 rec!/0 returns the num2er of 2"tes actuall" read into the 2uffer+ or ): on error /with errno set+ accordingl".0 :E 'here+ that was eas"+ wasn't it& 9ou can now pass data 2ac% and forth on stream soc%ets, $hee, 9ou're a Unix etwor% Programmer, sendto/0 and rec!from/0))'al% to me+ .G8-M)st"le 3'his is all fine and dand"+3 I hear "ou sa"ing+ 32ut where does this lea!e me with unconnected datagram soc%ets&3 o pro2lemo+ amigo. $e ha!e Bust the thing. (ince datagram soc%ets aren't connected to a remote host+ guess which piece of information we need to gi!e 2efore we send a pac%et& 'hat's right, 'he destination address, Here's the scoop# int sendto/int soc%fd+ const !oid Jmsg+ int len+ unsigned int flags+ const struct soc%addr Jto+ int tolen0F -s "ou can see+ this call is 2asicall" the same as the call to send/0 with the addition of two other pieces of information. to is a pointer to a struct soc%addr /which "ou'll pro2a2l" ha!e as a struct soc%addrGin and cast it at the last minute0 which contains the destination IP address and port. tolen can simpl" 2e set to siDeof/struct soc%addr0. Hust li%e with send/0+ sendto/0 returns the num2er of 2"tes actuall" sent /which+ again+ might 2e less than the num2er of 2"tes "ou told it to send,0+ or ): on error. ACuall" similar are rec!/0 and rec!from/0. 'he s"nopsis of rec!from/0 is# int rec!from/int soc%fd+ !oid J2uf+ int len+ unsigned int flags struct soc%addr Jfrom+ int Jfromlen0F -gain+ this is Bust li%e rec!/0 with the addition of a couple fields. from is a pointer to a local struct soc%addr that will 2e filled with the IP address and port of the originating machine. fromlen is a pointer to a local int that should 2e initialiDed to siDeof/struct soc%addr0. $hen the function returns+ fromlen will contain the length of the address actuall" stored in from. rec!from/0 returns the num2er of 2"tes recei!ed+ or ): on error /with errno set accordingl".0 8emem2er+ if "ou connect/0 a datagram soc%et+ "ou can then simpl" use send/0 and rec!/0 for all "our transactions. 'he soc%et itself is still a datagram soc%et and the pac%ets still use U.P+ 2ut the soc%et interface will automaticall" add the destination and source information for "ou. :O close/0 and shutdown/0))Get outta m" face, $hew, 9ou'!e 2een send/0'ing and rec!/0'ing data all da" long+ and "ou'!e had it. 9ou're read" to close the connection on "our soc%et descriptor. 'his is eas". 9ou can Bust use the regular Unix file descriptor close/0 function# close/soc%fd0F 'his will pre!ent an" more reads and writes to the soc%et. -n"one attempting to read or write the soc%et on the remote end will recei!e an error. Hust in case "ou want a little more control o!er how the soc%et closes+ "ou can use the shutdown/0 function. It allows "ou to cut off communication in a certain direction+ or 2oth wa"s /Bust li%e close/0 does.0 ("nopsis# int shutdown/int soc%fd+ int how0F soc%fd is the soc%et file descriptor "ou want to shutdown+ and how is one of the following# 7 ) 1urther recei!es are disallowed : ) 1urther sends are disallowed = ) 1urther sends and recei!es are disallowed /li%e close/00 shutdown/0 returns 7 on success+ and ): on error /with errno set accordingl".0 If "ou deign to use shutdown/0 on unconnected datagram soc%ets+ it will simpl" ma%e the soc%et una!aila2le for further send/0 and rec!/0 calls /remem2er that "ou can use these if "ou connect/0 "our datagram soc%et.0 othing to it. getpeername/0))$ho are "ou& 'his function is so eas". It's so eas"+ I almost didn't gi!e it it's own section. >ut here it is an"wa". 'he function getpeername/0 will tell "ou who is at the other end of a connected stream soc%et. 'he s"nopsis# Ninclude Ps"s?soc%et.hT int getpeername/int soc%fd+ struct soc%addr Jaddr+ int Jaddrlen0F :< soc%fd is the descriptor of the connected stream soc%et+ addr is a pointer to a struct soc%addr /or a struct soc%addrGin0 that will hold the information a2out the other side of the connection+ and addrlen is a pointer to an int+ that should 2e initialiDed to siDeof/struct soc%addr0. 'he function returns ): on error and sets errno accordingl". @nce "ou ha!e their address+ "ou can use inetGntoa/0 or gethost2"addr/0 to print or get more information. o+ "ou can't get their login name. /@%+ o%. If the other computer is running an ident daemon+ this is possi2le. 'his+ howe!er+ is 2e"ond the scope of this document. Chec% out 81C):5:4 for more info.0 gethostname/0))$ho am I& A!en easier than getpeername/0 is the function gethostname/0. It returns the name of the computer that "our program is running on. 'he name can then 2e used 2" gethost2"name/0+ 2elow+ to determine the IP address of "our local machine. $hat could 2e more fun& I could thin% of a few things+ 2ut the" don't pertain to soc%et programming. -n"wa"+ here's the 2rea%down# Ninclude Punistd.hT int gethostname/char Jhostname+ siDeGt siDe0F 'he function returns 7 on successful completion+ and ): on error+ setting errno as usual. . .())9ou sa" 3whitehouse.go!3+ I sa" 3:6;.:4<.=57.:773 In case "ou don't %now what .( is+ it stands for 3.omain ame (er!ice3. In a nutshell+ "ou tell it what the human)reada2le address is for a site+ and it'll gi!e "ou the IP address /so "ou can use it with 2ind/0+ connect/0+ sendto/0+ or whate!er "ou need it for.0 'his wa"+ when someone enters# X telnet whitehouse.go! telnet can find out that it needs to connect/0 to 3:6;.:4<.=57.:773. >ut how does it wor%& 9ou'll 2e using the function gethost2"name/0# :; Ninclude Pnetd2.hT
struct hostent Jgethost2"name/const char Jname0F -s "ou see+ it returns a pointer to a struct hostent+ the la"out of which is as follows# struct hostent I char JhGnameF char JJhGaliasesF int hGaddrt"peF int hGlengthF char JJhGaddrGlistF MF Ndefine hGaddr hGaddrGlistK7L -nd here are the descriptions of the fields in the struct hostent# hGname ) @fficial name of the host. hGaliases ) - ULL)terminated arra" of alternate names for the host. hGaddrt"pe ) 'he t"pe of address 2eing returnedF usuall" -1GIA'. hGlength ) 'he length of the address in 2"tes. hGaddrGlist ) - Dero)terminated arra" of networ% addresses for the host. Host addresses are in etwor% >"te @rder. hGaddr ) 'he first address in hGaddrGlist. gethost2"name/0 returns a pointer to the filled struct hostent+ or ULL on error. />ut errno is not set))hGerrno is set instead. (ee herror/0+ 2elow.0 >ut how is it used& (ometimes /as we find from reading computer manuals0+ Bust spewing the information at the reader is not enough. 'his function is certainl" easier to use than it loo%s. Here's an example program# Ninclude Pstdio.hT Ninclude Pstdli2.hT Ninclude Perrno.hT Ninclude Pnetd2.hT Ninclude Ps"s?t"pes.hT Ninclude Pnetinet?in.hT int main/int argc+ char Jarg!KL0 I struct hostent JhF if /argc ,Q =0 I ?J error chec% the command line J? fprintf/stderr+3usage# getip addressSn30F :6 exit/:0F M if //hQgethost2"name/arg!K:L00 QQ ULL0 I ?J get the host info J? herror/3gethost2"name30F exit/:0F M printf/3Host name # RsSn3+ h)ThGname0F printf/3IP -ddress # RsSn3+inetGntoa/J//struct inGaddr J0h)ThGaddr000F return 7F M $ith gethost2"name/0+ "ou can't use perror/0 to print error message /since errno is not used0. Instead+ call herror/0. It's prett" straightforward. 9ou simpl" pass the string that contains the machine name /3whitehouse.go!30 to gethost2"name/0+ and then gra2 the information out of the returned struct hostent. 'he onl" possi2le weirdness might 2e in the printing of the IP address+ a2o!e. h) ThGaddr is a char J+ 2ut inetGntoa/0 wants a struct inGaddr passed to it. (o I cast h)ThGaddr to a struct inGaddr J+ then dereference it to get at the data. Client)(er!er >ac%ground It's a client)ser!er world+ 2a2". Hust a2out e!er"thing on the networ% deals with client processes tal%ing to ser!er processes and !ice)!ersa. 'a%e telnet+ for instance. $hen "ou connect to a remote host on port =4 with telnet /the client0+ a program on that host /called telnetd+ the ser!er0 springs to life. It handles the incoming telnet connection+ sets "ou up with a login prompt+ etc. =7 1igure =. 'he Client)(er!er 8elationship. 'he exchange of information 2etween client and ser!er is summariDed in 1igure =. ote that the client)ser!er pair can spea% (@C*G('8A-M+ (@C*G.G8-M+ or an"thing else /as long as the"'re spea%ing the same thing.0 (ome good examples of client) ser!er pairs are telnet?telnetd+ ftp?ftpd+ or 2ootp?2ootpd. A!er" time "ou use ftp+ there's a remote program+ ftpd+ that ser!es "ou. @ften+ there will onl" 2e one ser!er on a machine+ and that ser!er will handle multiple clients using for%/0. 'he 2asic routine is# ser!er will wait for a connection+ accept/0 it+ and for%/0 a child process to handle it. 'his is what our sample ser!er does in the next section. - (imple (tream (er!er -ll this ser!er does is send the string 3Hello+ $orld,Sn3 out o!er a stream connection. -ll "ou need to do to test this ser!er is run it in one window+ and telnet to it from another with# X telnet remotehostname 4567 where remotehostname is the name of the machine "ou're running it on. 'he ser!er code# /ote# a trailing 2ac%slash on a line means that the line is continued on the next.0 Ninclude Pstdio.hT Ninclude Pstdli2.hT Ninclude Perrno.hT Ninclude Pstring.hT Ninclude Ps"s?t"pes.hT Ninclude Pnetinet?in.hT =: Ninclude Ps"s?soc%et.hT Ninclude Ps"s?wait.hT Ndefine M9P@8' 4567 ?J the port users will 2e connecting to J? Ndefine >-C*L@G :7 ?J how man" pending connections Cueue will hold J? main/0 I int soc%fd+ newGfdF ?J listen on soc%Gfd+ new connection on newGfd J? struct soc%addrGin m"GaddrF ?J m" address information J? struct soc%addrGin theirGaddrF ?J connector's address information J? int sinGsiDeF if //soc%fd Q soc%et/-1GIA'+ (@C*G('8A-M+ 700 QQ ):0 I perror/3soc%et30F exit/:0F M m"Gaddr.sinGfamil" Q -1GIA'F ?J host 2"te order J? m"Gaddr.sinGport Q htons/M9P@8'0F ?J short+ networ% 2"te order J? m"Gaddr.sinGaddr.sGaddr Q I-..8G-9F ?J auto)fill with m" IP J? 2Dero/U/m"Gaddr.sinGDero0+ ;0F ?J Dero the rest of the struct J? if /2ind/soc%fd+ /struct soc%addr J0Um"Gaddr+ siDeof/struct soc%addr00 S QQ ):0 I perror/32ind30F exit/:0F M if /listen/soc%fd+ >-C*L@G0 QQ ):0 I perror/3listen30F exit/:0F M while/:0 I ?J main accept/0 loop J? sinGsiDe Q siDeof/struct soc%addrGin0F if //newGfd Q accept/soc%fd+ /struct soc%addr J0UtheirGaddr+ S UsinGsiDe00 QQ ):0 I perror/3accept30F continueF M == printf/3ser!er# got connection from RsSn3+ S inetGntoa/theirGaddr.sinGaddr00F if /,for%/00 I ?J this is the child process J? if /send/newGfd+ 3Hello+ world,Sn3+ :5+ 70 QQ ):0 perror/3send30F close/newGfd0F exit/70F M close/newGfd0F ?J parent doesn't need this J? while/waitpid/):+ULL+$@H-G0 T 70F ?J clean up child processes J? M M In case "ou're curious+ I ha!e the code in one 2ig main/0 function for /I feel0 s"ntactic clarit". 1eel free to split it into smaller functions if it ma%es "ou feel 2etter. 9ou can also get the string from this ser!er 2" using the client listed in the next section. - (imple (tream Client 'his gu"'s e!en easier than the ser!er. -ll this client does is connect to the host "ou specif" on the command line+ port 4567. It gets the string that the ser!er sends. 'he client source# Ninclude Pstdio.hT Ninclude Pstdli2.hT Ninclude Perrno.hT Ninclude Pstring.hT Ninclude Pnetd2.hT Ninclude Ps"s?t"pes.hT Ninclude Pnetinet?in.hT Ninclude Ps"s?soc%et.hT Ndefine P@8' 4567 ?J the port client will 2e connecting to J? Ndefine M-X.-'-(IVA :77 ?J max num2er of 2"tes we can get at once J? int main/int argc+ char Jarg!KL0 I =4 int soc%fd+ num2"tesF char 2ufKM-X.-'-(IVALF struct hostent JheF struct soc%addrGin theirGaddrF ?J connector's address information J? if /argc ,Q =0 I fprintf/stderr+3usage# client hostnameSn30F exit/:0F M if //heQgethost2"name/arg!K:L00 QQ ULL0 I ?J get the host info J? herror/3gethost2"name30F exit/:0F M if //soc%fd Q soc%et/-1GIA'+ (@C*G('8A-M+ 700 QQ ):0 I perror/3soc%et30F exit/:0F M theirGaddr.sinGfamil" Q -1GIA'F ?J host 2"te order J? theirGaddr.sinGport Q htons/P@8'0F ?J short+ networ% 2"te order J? theirGaddr.sinGaddr Q J//struct inGaddr J0he)ThGaddr0F 2Dero/U/theirGaddr.sinGDero0+ ;0F ?J Dero the rest of the struct J? if /connect/soc%fd+ /struct soc%addr J0UtheirGaddr+ S siDeof/struct soc%addr00 QQ ):0 I perror/3connect30F exit/:0F M if //num2"tesQrec!/soc%fd+ 2uf+ M-X.-'-(IVA+ 700 QQ ):0 I perror/3rec!30F exit/:0F M 2ufKnum2"tesL Q 'S7'F printf/38ecei!ed# Rs3+2uf0F close/soc%fd0F =5 return 7F M otice that if "ou don't run the ser!er 2efore "ou run the client+ connect/0 returns 3Connection refused3. Wer" useful. .atagram (oc%ets I reall" don't ha!e that much to tal% a2out here+ so I'll Bust present a couple of sample programs# tal%er.c and listener.c. listener sits on a machine waiting for an incoming pac%et on port 56E7. tal%er sends a pac%et to that port+ on the specified machine+ that contains whate!er the user enters on the command line. Here is the source for listener.c# Ninclude Pstdio.hT Ninclude Pstdli2.hT Ninclude Perrno.hT Ninclude Pstring.hT Ninclude Ps"s?t"pes.hT Ninclude Pnetinet?in.hT Ninclude Ps"s?soc%et.hT Ninclude Ps"s?wait.hT Ndefine M9P@8' 56E7 ?J the port users will 2e sending to J? Ndefine M-X>U1LA :77 main/0 I int soc%fdF struct soc%addrGin m"GaddrF ?J m" address information J? struct soc%addrGin theirGaddrF ?J connector's address information J? int addrGlen+ num2"tesF char 2ufKM-X>U1LALF if //soc%fd Q soc%et/-1GIA'+ (@C*G.G8-M+ 700 QQ ):0 I perror/3soc%et30F exit/:0F =E M m"Gaddr.sinGfamil" Q -1GIA'F ?J host 2"te order J? m"Gaddr.sinGport Q htons/M9P@8'0F ?J short+ networ% 2"te order J? m"Gaddr.sinGaddr.sGaddr Q I-..8G-9F ?J auto)fill with m" IP J? 2Dero/U/m"Gaddr.sinGDero0+ ;0F ?J Dero the rest of the struct J? if /2ind/soc%fd+ /struct soc%addr J0Um"Gaddr+ siDeof/struct soc%addr00 S QQ ):0 I perror/32ind30F exit/:0F M addrGlen Q siDeof/struct soc%addr0F if //num2"tesQrec!from/soc%fd+ 2uf+ M-X>U1LA+ 7+ S /struct soc%addr J0UtheirGaddr+ UaddrGlen00 QQ ):0 I perror/3rec!from30F exit/:0F M printf/3got pac%et from RsSn3+inetGntoa/theirGaddr.sinGaddr00F printf/3pac%et is Rd 2"tes longSn3+num2"tes0F 2ufKnum2"tesL Q 'S7'F printf/3pac%et contains S3RsS3Sn3+2uf0F close/soc%fd0F M otice that in our call to soc%et/0 we're finall" using (@C*G.G8-M. -lso+ note that there's no need to listen/0 or accept/0. 'his is one of the per%s of using unconnected datagram soc%ets, ext comes the source for tal%er.c# Ninclude Pstdio.hT Ninclude Pstdli2.hT Ninclude Perrno.hT Ninclude Pstring.hT Ninclude Ps"s?t"pes.hT Ninclude Pnetinet?in.hT Ninclude Pnetd2.hT Ninclude Ps"s?soc%et.hT Ninclude Ps"s?wait.hT =O Ndefine M9P@8' 56E7 ?J the port users will 2e sending to J? int main/int argc+ char Jarg!KL0 I int soc%fdF struct soc%addrGin theirGaddrF ?J connector's address information J? struct hostent JheF int num2"tesF if /argc ,Q 40 I fprintf/stderr+3usage# tal%er hostname messageSn30F exit/:0F M if //heQgethost2"name/arg!K:L00 QQ ULL0 I ?J get the host info J? herror/3gethost2"name30F exit/:0F M if //soc%fd Q soc%et/-1GIA'+ (@C*G.G8-M+ 700 QQ ):0 I perror/3soc%et30F exit/:0F M theirGaddr.sinGfamil" Q -1GIA'F ?J host 2"te order J? theirGaddr.sinGport Q htons/M9P@8'0F ?J short+ networ% 2"te order J? theirGaddr.sinGaddr Q J//struct inGaddr J0he)ThGaddr0F 2Dero/U/theirGaddr.sinGDero0+ ;0F ?J Dero the rest of the struct J? if //num2"tesQsendto/soc%fd+ arg!K=L+ strlen/arg!K=L0+ 7+ S /struct soc%addr J0UtheirGaddr+ siDeof/struct soc%addr000 QQ ):0 I perror/3sendto30F exit/:0F M printf/3sent Rd 2"tes to RsSn3+num2"tes+inetGntoa/theirGaddr.sinGaddr00F close/soc%fd0F return 7F M =< -nd that's all there is to it, 8un listener on some machine+ then run tal%er on another. $atch them communicate, 1un G)rated excitement for the entire nuclear famil", Axcept for one more tin" detail that I'!e mentioned man" times in the past# connected datagram soc%ets. I need to tal% a2out this here+ since we're in the datagram section of the document. Let's sa" that tal%er calls connect/0 and specifies the listener's address. 1rom that point on+ tal%er ma" onl" sent to and recei!e from the address specified 2" connect/0. 1or this reason+ "ou don't ha!e to use sendto/0 and rec!from/0F "ou can simpl" use send/0 and rec!/0. >loc%ing >loc%ing. 9ou'!e heard a2out it))now what the hell is it& In a nutshell+ 32loc%3 is techie Bargon for 3sleep3. 9ou pro2a2l" noticed that when "ou run listener+ a2o!e+ it Bust sits there until a pac%et arri!es. $hat happened is that it called rec!from/0+ there was no data+ and so rec!from/0 is said to 32loc%3 /that is+ sleep there0 until some data arri!es. Lots of functions 2loc%. accept/0 2loc%s. -ll the rec!J/0 functions 2loc%. 'he reason the" can do this is 2ecause the"'re allowed to. $hen "ou first create the soc%et descriptor with soc%et/0+ the %ernel sets it to 2loc%ing. If "ou don't want a soc%et to 2e 2loc%ing+ "ou ha!e to ma%e a call to fcntl/0# Ninclude Punistd.hT Ninclude Pfcntl.hT . . soc%fd Q soc%et/-1GIA'+ (@C*G('8A-M+ 70F fcntl/soc%fd+ 1G(A'1L+ @G@>L@C*0F . . >" setting a soc%et to non)2loc%ing+ "ou can effecti!el" 3poll3 the soc%et for information. If "ou tr" to read from a non)2loc%ing soc%et and there's no data there+ it's not allowed to 2loc%))it will return ): and errno will 2e set to A$@UL.>L@C*. Generall" spea%ing+ howe!er+ this t"pe of polling is a 2ad idea. If "ou put "our program in a 2us")wait loo%ing for data on the soc%et+ "ou'll suc% up CPU time li%e it was going out of st"le. - more elegant solution for chec%ing to see if there's data waiting to 2e read comes in the following section on select/0. =; select/0))("nchronous I?@ Multiplexing 'his function is somewhat strange+ 2ut it's !er" useful. 'a%e the following situation# "ou are a ser!er and "ou want to listen for incoming connections as well as %eep reading from the connections "ou alread" ha!e. o pro2lem+ "ou sa"+ Bust an accept/0 and a couple of rec!/0s. ot so fast+ 2uster, $hat if "ou're 2loc%ing on an accept/0 call& How are "ou going to rec!/0 data at the same time& 3Use non)2loc%ing soc%ets,3 o wa", 9ou don't want to 2e a CPU hog. $hat+ then& select/0 gi!es "ou the power to monitor se!eral soc%ets at the same time. It'll tell "ou which ones are read" for reading+ which are read" for writing+ and which soc%ets ha!e raised exceptions+ if "ou reall" want to %now that. $ithout an" further ado+ I'll offer the s"nopsis of select/0# Ninclude Ps"s?time.hT Ninclude Ps"s?t"pes.hT Ninclude Punistd.hT int select/int numfds+ fdGset Jreadfds+ fdGset Jwritefds+ fdGset Jexceptfds+ struct time!al Jtimeout0F 'he function monitors 3sets3 of file descriptorsF in particular readfds+ writefds+ and exceptfds. If "ou want to see if "ou can read from standard input and some soc%et descriptor+ soc%fd+ Bust add the file descriptors 7 and soc%fd to the set readfds. 'he parameter numfds should 2e set to the !alues of the highest file descriptor plus one. In this example+ it should 2e set to soc%fdY:+ since it is assuredl" higher than standard input /70. $hen select/0 returns+ readfds will 2e modified to reflect which of the file descriptors "ou selected is read" for reading. 9ou can test them with the macro 1.GI((A'/0+ 2elow. >efore progressing much further+ I'll tal% a2out how to manipulate these sets. Aach set is of the t"pe fdGset. 'he following macros operate on this t"pe# 1.GVA8@/fdGset Jset0 ) clears a file descriptor set 1.G(A'/int fd+ fdGset Jset0 ) adds fd to the set 1.GCL8/int fd+ fdGset Jset0 ) remo!es fd from the set 1.GI((A'/int fd+ fdGset Jset0 ) tests to see if fd is in the set =6 1inall"+ what is this weirded out struct time!al& $ell+ sometimes "ou don't want to wait fore!er for someone to send "ou some data. Ma"2e e!er" 6O seconds "ou want to print 3(till Going...3 to the terminal e!en though nothing has happened. 'his time structure allows "ou to specif" a timeout period. If the time is exceeded and select/0 still hasn't found an" read" file descriptors+ it'll return so "ou can continue processing. 'he struct time!al has the follow fields# struct time!al I int t!GsecF ?J seconds J? int t!GusecF ?J microseconds J? MF Hust set t!Gsec to the num2er of seconds to wait+ and set t!Gusec to the num2er of microseconds to wait. 9es+ that's microseconds+ not milliseconds. 'here are :+777 microseconds in a millisecond+ and :+777 milliseconds in a second. 'hus+ there are :+777+777 microseconds in a second. $h" is it 3usec3& 'he 3u3 is supposed to loo% li%e the Gree% letter Mu that we use for 3micro3. -lso+ when the function returns+ timeout might 2e updated to show the time still remaining. 'his depends on what fla!or of Unix "ou're running. 9a", $e ha!e a microsecond resolution timer, $ell+ don't count on it. (tandard Unix timeslice is :77 milliseconds+ so "ou'll pro2a2l" ha!e to wait at least that long+ no matter how small "ou set "our struct time!al. @ther things of interest# If "ou set the fields in "our struct time!al to 7+ select/0 will timeout immediatel"+ effecti!el" polling all the file descriptors in "our sets. If "ou set the parameter timeout to ULL+ it will ne!er timeout+ and will wait until the first file descriptor is read". 1inall"+ if "ou don't care a2out waiting for a certain set+ "ou can Bust set it to ULL in the call to select/0. 'he following code snippet waits =.E seconds for something to appear on standard input# Ninclude Ps"s?time.hT Ninclude Ps"s?t"pes.hT Ninclude Punistd.hT Ndefine ('.I 7 ?J file descriptor for standard input J? main/0 I struct time!al t!F fdGset readfdsF 47 t!.t!Gsec Q =F t!.t!Gusec Q E77777F 1.GVA8@/Ureadfds0F 1.G(A'/('.I+ Ureadfds0F ?J don't care a2out writefds and exceptfds# J? select/('.IY:+ Ureadfds+ ULL+ ULL+ Ut!0F if /1.GI((A'/('.I+ Ureadfds00 printf/3- %e" was pressed,Sn30F else printf/3'imed out.Sn30F M If "ou're on a line 2uffered terminal+ the %e" "ou hit should 2e 8A'U8 or it will time out an"wa". ow+ some of "ou might thin% this is a great wa" to wait for data on a datagram soc%et))and "ou are right# it might 2e. (ome Unices can use select in this manner+ and some can't. 9ou should see what "our local man page sa"s on the matter if "ou want to attempt it. @ne final note of interest a2out select/0# if "ou ha!e a soc%et that is listen/0'ing+ "ou can chec% to see if there is a new connection 2" putting that soc%et's file descriptor in the readfds set. 9ou'!e come this far+ and now "ou're screaming for more, $here else can "ou go to learn more a2out all this stuff& 'r" the following man pages+ for starters# soc%et/0 2ind/0 connect/0 listen/0 accept/0 send/0 rec!/0 sendto/0 rec!from/0 4: close/0 shutdown/0 getpeername/0 getsoc%name/0 gethost2"name/0 gethost2"addr/0 getproto2"name/0 fcntl/0 select/0 perror/0 4=