Tải bản đầy đủ - 0 (trang)
Chapter 2. The Transport Layer: TCP, UDP, and SCTP

Chapter 2. The Transport Layer: TCP, UDP, and SCTP

Tải bản đầy đủ - 0trang

signedintegers.Thereasonwhyisthatsomeofthe

STREAMSfunctionsusealenormaxlenvalueof1to

indicatesomethingspecial.

Wecansendonlycontrolinformation,onlydata,orbothusing

putmsg.Toindicatetheabsenceofcontrolinformation,wecan

eitherspecifyctlptrasanullpointerorsetctlptr->lento1.The

sametechniqueisusedtoindicatenodata.

Ifthereisnocontrolinformation,anM_DATAmessageis

generatedbyputmsg(Figure31.6);otherwise,eitheran

M_PROTOoranM_PCPROTOmessageisgenerated,dependingon

theflags.Theflagsargumenttoputmsgis0foranormal

messageorRS_HIPRIforahigh-prioritymessage.

Thefinalargumenttogetmsgisavalue-resultargument.Ifthe

integerpointedtobyflagspis0whenthefunctioniscalled,the

firstmessageonthestreamisreturned(whichcanbenormalorhigh-priority).IftheintegervalueisRS_HIPRIwhenthe

functioniscalled,thefunctionwaitsforahigh-prioritymessage

toarriveatthestreamhead.Inbothcases,thevaluestoredin

theintegerpointedtobyflagspwillbe0orRS_HIPRI,

dependingonthetypeofmessagereturned.

Assumingwepassnon-nullctlptranddataptrvaluestogetmsg,

ifthereisnocontrolinformationtoreturn(i.e.,anM_DATA

messageisbeingreturned),thisisindicatedbysettingctlptr>lento1onreturn.Similarly,dataptr->lenissetto1ifthereis

nodatatoreturn.

Thereturnvaluefromputmsgis0ifallisokay,or1onanerror.

But,getmsgreturns0onlyiftheentiremessagewasreturned

tothecaller.Ifthecontrolbufferistoosmallforallthecontrol

information,thereturnvalueisMORECTL(whichisguaranteed

tobenon-negative).Similarly,ifthedatabufferistoosmall,

MOREDATAcanbereturned.Ifbotharetoosmall,thelogicalOR

ofthesetwoflagsisreturned.



31.4getpmsgandputpmsgFunctions

Whensupportfordifferentprioritybandswasaddedto

STREAMSwithSVR4,thefollowingtwovariantsofgetmsgand

putmsgwereadded:



#include



intgetpmsg(intfd,structstrbuf*ctlptr,structstrbuf*dataptr,int*bandp,

int*flagsp);



intputpmsg(intfd,conststructstrbuf*ctlptr,conststructstrbuf*dataptr,

intband,intflags);

Bothreturn:non-negativevalueifOK,1onerror



Thebandargumenttoputpmsgmustbebetween0and255,

inclusive.IftheflagsargumentisMSG_BAND,thenamessageis

generatedinthespecifiedpriorityband.Settingflagsto

MSG_BANDandspecifyingabandof0isequivalenttocalling

putmsg.IfflagsisMSG_HIPRI,bandmustbe0,andahighprioritymessageisgenerated.(Notethatthisflagisnamed

differentlyfromtheRS_HIPRIflagforputmsg.)

Thetwointegerspointedtobybandpandflagsparevalueresultargumentsforgetpmsg.Theintegerpointedtobyflagsp

forgetpmsgcanbeMSG_HIPRI(toreadahigh-priority

message),MSG_BAND(toreadamessagewhoseprioritybandis

atleastequaltotheintegerpointedtobybandp),orMSG_ANY

(toreadanymessage).Onreturn,theintegerpointedtoby

bandpcontainsthebandofthemessagethatwasreadandthe

integerpointedtobyflagspcontainsMSG_HIPRI(ifahighprioritymessagewasread)orMSG_BAND(ifsomeother

messagewasread).



31.5ioctlFunction

WithSTREAMS,weagainencountertheioctlfunctionthatwas

describedinChapter17.



#include



intioctl(intfd,intrequest,.../*void*arg*/);

Returns:0ifOK,1onerror



TheonlychangefromthefunctionprototypeshowninSection

17.2istheheadersthatmustbeincludedwhendealingwith

STREAMS.

Thereareabout30requeststhataffectastreamhead.Each

requestbeginswithI_andtheyarenormallydocumentedon

thestreamiomanpage.



31.6TransportProviderInterface(TPI)

InFigure31.3,weshowedthatTPIistheserviceinterfaceinto

thetransportlayerfromabove.BothsocketsandXTIusethis

interfaceinaSTREAMSenvironment.InFigure31.3,itisa

combinationofthesocketslibraryandsockmod,alongwitha

combinationoftheXTIlibraryandtimod,thatexchangeTPI

messageswithTCPandUDP.

TPIisamessage-basedinterface.Itdefinesthemessagesthat

areexchangedupanddownastreambetweentheapplication

(e.g.,thesocketslibrary)andthetransportlayer:theformatof

thesemessagesandwhatoperationeachmessageperforms.In

manyinstances,theapplicationsendsarequesttotheprovider

(suchas"bindthislocaladdress")andtheprovidersendsback

aresponse("OK"or"error").Someeventsoccur

asynchronouslyattheprovider(thearrivalofaconnection

requestforaserver),causingamessageorasignaltobesent

upthestream.

WeareabletobypassbothsocketsandXTIanduseTPI

directly.Inthissection,wewillrewriteoursimpledaytime

clientusingTPIinsteadofsockets(Figure1.5).Using

programminglanguagesasananalogy,usingsocketsislike

programminginahigh-levellanguagesuchasCorPascal,

whileusingTPIdirectlyislikeprogramminginassembly

language.WearenotadvocatingtheuseofTPIdirectlyinreal

applications.ButexamininghowTPIworksanddevelopingthis

examplegiveusabetterunderstandingofhowthesockets

libraryworksinaSTREAMSenvironment.

Figure31.7isourtpi_daytime.hheader.



Figure31.7Ourtpi_daytime.hheader.



streams/tpi_daytime.h

1#include"unpxti.h"

2#include

3#include

4voidtpi_bind(int,constvoid*,size_t);

5voidtpi_connect(int,constvoid*,size_t);

6ssize_ttpi_read(int,void*,size_t);

7voidtpi_close(int);

WeneedtoincludeoneadditionalSTREAMSheaderalongwith

,whichcontainsthedefinitionsofthestructures

forallTPImessages.

Figure31.8isthemainfunctionforourdaytimeclient.



Figure31.8mainfunctionforourdaytimeclient

writtentoTPI.

streams/tpi_daytime.c

1#include"tpi_daytime.h"

2int

3main(intargc,char**argv)

4{

5intfd,n;

6charrecvline[MAXLINE+1];

7structsockaddr_inmyaddr,servaddr;

8if(argc!=2)

9err_quit("usage:tpi_daytime");

10fd=Open(XTI_TCP,O_RDWR,0);



11/*bindanylocaladdress*/

12bzero(&myaddr,sizeof(myaddr));

13myaddr.sin_family=AF_INET;

14myaddr.sin_addr.s_addr=htonl(INADDR_ANY);

15myaddr.sin_port=htons(0);

16tpi_bind(fd,&myaddr,sizeof(structsockaddr_in));

17/*fillinserver'saddress*/

18bzero(&servaddr,sizeof(servaddr));

19servaddr.sin_family=AF_INET;

20servaddr.sin_port=htons(13);/*daytimeserver*/

21Inet_pton(AF_INET,argv[1],&servaddr.sin_addr);

22tpi_connect(fd,&servaddr,sizeof(structsockaddr_in));

23for(;;){

24if((n=tpi_read(fd,recvline,MAXLINE))<=0){

25if(n==0)

26break;

27else

28err_sys("tpi_readerror");

29}

30recvline[n]=0;/*nullterminate*/

31fputs(recvline,stdout);

32}

33tpi_close(fd);

34exit(0);

35}



Opentransportprovider,bindlocaladdress

1016Weopenthedevicecorrespondingtothetransport

provider(normally/dev/tcp).WefillinanInternetsocket

addressstructurewithINADDR_ANYandaportof0,tellingTCP



tobindanylocaladdresstoourendpoint.Wecallourown

functiontpi_bind(shownshortly)todothebind.



Fillinserver'saddress,establishconnection

1722WefillinanotherInternetsocketaddressstructurewith

theserver'sIPaddress(takenfromthecommandline)andport

(13).Wecallourtpi_connectfunctiontoestablishthe

connection.



Readdatafromserver,copytostandardoutput

2333Asinourotherdaytimeclients,wejustcopydatafrom

theconnectiontostandardoutput,stoppingwhenwereceive

theEOFfromtheserver(e.g.,theFIN).Wethencallour

tpi_closefunctiontocloseourendpoint.

Ourtpi_bindfunctionisshowninFigure31.9.



FillinT_bind_reqstructure

1620TheheaderdefinestheT_bind_req

structure.



structT_bind_req{

t_scalar_tPRIM_type;/*T_BIND_REQ*/

t_scalar_tADDR_length;/*addresslength*/

t_scalar_tADDR_offset;/*addressoffset*/

t_uscalar_tCONIND_number;/*connectindicationsrequest

/*followedbytheprotocoladdressforbind*/

};



AllTPIrequestsaredefinedasastructurethatbeginswitha

longintegertypefield.Wedefineourownbind_reqstructure

thatbeginswiththeT_bind_reqstructure,followedbyabuffer

containingthelocaladdresstobebound.TPIsaysnothing

aboutthecontentsofthisbuffer;itisdefinedbytheprovider.

TCPprovidersexpectthisbuffertocontainasockaddr_in

structure.

WefillintheT_bind_reqstructure,settingtheADDR_length

membertothesizeoftheaddress(16bytesforanInternet

socketaddressstructure)andADDR_offsettothebyteoffsetof

theaddress(itimmediatelyfollowstheT_bind_reqstructure).

Wearenotguaranteedthatthislocationissuitablyalignedfor

thesockaddr_instructurethatisstoredthere,sowecall

memcpytocopythecaller'sstructureintoourbind_req

structure.WesetCONIND_numberto0becauseweareaclient,

notaserver.



Callputmsg

2123TPIrequiresthestructurethatwejustbuilttobepassed

totheproviderasoneM_PROTOmessage.Wethereforecall

putmsg,specifyingourbind_reqstructureasthecontrol

information,withnodataandwithaflagof0.



Callgetmsgtoreadhigh-prioritymessage

2430TheresponsetoourT_BIND_REQrequestwillbeeithera

T_BIND_ACKmessageoraT_ERROR_ACKmessage.These

acknowledgmentmessagesaresentashigh-prioritymessages

(M_PCPROTO)sowereadthemusinggetmsgwithaflagof

RS_HIPRI.Sincethereplyisahigh-prioritymessage,itwill

bypassanynormal-prioritymessagesonthestream.



Figure31.9tpi_bindfunction:bindsalocal

addresstoanendpoint.

streams/tpi_bind.c

1#include"tpi_daytime.h"

2void

3tpi_bind(intfd,constvoid*addr,size_taddrlen)

4{

5struct{

6structT_bind_reqmsg_hdr;

7charaddr[128];

8}bind_req;

9struct{

10structT_bind_ackmsg_hdr;

11charaddr[128];

12}bind_ack;

13structstrbufctlbuf;

14structT_error_ack*error_ack;

15intflags;



16bind_req.msg_hdr.PRIM_type=T_BIND_REQ;

17bind_req.msg_hdr.ADDR_length=addrlen;

18bind_req.msg_hdr.ADDR_offset=sizeof(structT_bind_req)

19bind_req.msg_hdr.CONIND_number=0;

20memcpy(bind_req.addr,addr,addrlen);/*sockaddr_in{}

21ctlbuf.len=sizeof(structT_bind_req)+addrlen;

22ctlbuf.buf=(char*)&bind_req;

23Putmsg(fd,&ctlbuf,NULL,0);

24ctlbuf.maxlen=sizeof(bind_ack);

25ctlbuf.len=0;

26ctlbuf.buf=(char*)&bind_ack;

27flags=RS_HIPRI;



28Getmsg(fd,&ctlbuf,NULL,&flags);

29if(ctlbuf.len<(int)sizeof(long))

30err_quit("badlengthfromgetmsg");

31switch(bind_ack.msg_hdr.PRIM_type){

32caseT_BIND_ACK:

33return;



34caseT_ERROR_ACK:

35if(ctlbuf.len<(int)sizeof(structT_error_ack))

36err_quit("badlengthforT_ERROR_ACK");

37error_ack=(structT_error_ack*)&bind_ack.msg_hdr

38err_quit("T_ERROR_ACKfrombind(%d,%d)",

39error_ack->TLI_error,error_ack->UNIX_error



40default:

41err_quit("unexpectedmessagetype:%d",bind_ack.msg

42}

43}

Thesetwomessagesareasfollows:



structT_bind_ack{

t_scalar_tPRIM_type;/*T_BIND_ACK*/

t_scalar_tADDR_length;/*addresslength*/

t_scalar_tADDR_offset;/*addressoffset*/

t_uscalar_tCONIND_number;/*connectindtobequeued*/

/*followedbytheboundaddress*/

};

structT_error_ack{

t_scalar_tPRIM_type;/*T_ERROR_ACK*/

t_scalar_tERROR_prim/*primitiveinerror*/

t_scalar_tTLI_error;/*TLIerrorcode*/

t_scalar_tUNIX_error;/*UNIXerrorcode*/



};

Allthesemessagesbeginwiththetype,sowecanreadthe

replyassumingitisaT_BIND_ACKmessage,lookatthetype,

andprocessthemessageaccordingly.Wedonotexpectany

datafromtheprovider,sowespecifyanullpointerasthethird

argumenttogetmsg.

Whenweverifythattheamountofcontrolinformation

returnedisatleastthesizeofalonginteger,wemustbe

carefultocastthesizeofvaluetoaninteger.Thesizeof

operatorreturnsanunsignedintegervalue,butitis

possibleforthereturnedlenfieldtobe1.Butsincethe

less-thancomparisoniscomparingasignedvalueonthe

lefttoanunsignedvalueontheright,thecompilercasts

thesignedvaluetoanunsignedvalue.Onatwo'scomplementarchitecture,1,consideredasanunsigned

value,isverylarge,causing1tobegreaterthan4(ifwe

assumealongintegeroccupies4bytes).



Processreply

3133IfthereplyisT_BIND_ACK,thebindwassuccessfulandwe

return.Theactualaddressthatwasboundtotheendpointis

returnedintheaddrmemberofourbind_ackstructure,which

weignore.

3439IfthereplyisT_ERROR_ACK,weverifythattheentire

messagewasreceivedandthenprintthethreereturnvaluesin

thestructure.Inthissimpleprogram,weterminatewhenan

erroroccurs;wedonotreturntothecaller.

Wecanseetheseerrorsfromthebindrequestbychangingour

mainfunctiontobindsomeportotherthan0.Forexample,if

wetrytobindport1(whichrequiressuperuserprivileges,since



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 2. The Transport Layer: TCP, UDP, and SCTP

Tải bản đầy đủ ngay(0 tr)

×