ࡱ> 7 YbjbjUU 77|7|;:7l       & 2.2.2.8j../& [`&1&1&1&1&1&1&1&1xXzXzXzX<XdYd~Y$\  _Y &1&1&1&1&1Y I  &1&1C[ I I I&1b  &1 &1xX I&1xX I IJ  J&11 @Eb& "2.<v JJ| Y[0[J_H"_J I& &     Understanding Network Connections Butler Lampson There are lots of protocols for establishing connections (or equivalently, doing at-most-once message delivery) across a network that can delay, reorder, duplicate and lose packets. Most of the popular ones are based on three-way handshake, but some use clocks or extra stable storage operations to reduce the number of messages required. Its hard to understand why the protocols work, and there are almost no correctness proofs; even careful specifications are rare. I will give a specification for at-most-once message delivery, an informal account of the main problems an implementation must solve and the common features that most implementations share, and outlines of proofs for three implementations. The specifications and proofs based on Lamports methods for using abstraction functions to understand concurrent systems, and I will say something about how his methods can be applied to many other problems of practical interest. Understanding Network Connections Butler Lampson October 30, 1995 This is joint work with Nancy Lynch. The errors in this talk are mine, however. Overview Specify at-most-once message delivery. Describe other features we want from an implementation Give a framework for thinking about implementations. Show how to prove correctness of an implementation. The Problem Network Connections or Reliable At-Most-Once Messages Messages are delivered in fifo order. A message is not delivered more than once. A message is acked only if delivered. A message or ack is lost only if it is being sent between crash and recovery. Pragmatics Everything should be made as simple as possible, but no simpler. A. Einstein Make progress: regardless of crashes, if both ends stay up a waiting message is sent, and otherwise both parties become idle. Idle at no cost: an idle agent has no state that changes for each message, and doesnt send any packets. Minimize stable storage operations <<1 per message. Use channels that are easy to implement: They may lose, duplicate, or reorder messages. Pragmatics Some pragmatic issues we wont discuss: Retransmission policy. Detecting failure of an attempt to send or ack, by timing it out. Describing a System A system is defined by a safety and a liveness property: Safety: nothing bad ever happens. Defined by a state machine: A set of states. A state is a pair (external state, internal state) A set of initial states. A set of transitions from one state to another. Liveness: something good eventually happens. An action is a named set of transitions; actions partition the transitions. For instance: put(m); get(m); crashs A history is a possible sequence of actions, starting from an initial state. The behavior of the system is the set of possible histories. An external action is one in which the external state changes. Correspondingly there are external histories and behaviors. Defining Actions An action is: A name, possibly with parameters: put(red). A guard, a predicate on the state which must be true for this action to be a possible transition: q `" < > and i > 3. An effect, changes in some of the state variables: i := i + 1. The entire action is atomic. Example: get(m): m first on q take first from q, if q now empty and status = ? then status := true name guard effect Specifying At-Most-Once Messages State: q : sequence[M] := < > status : {true, false, ?} := true recs/r : Boolean := false Sender ActionsReceiver ActionsNameGuardEffectNameGuardEffectput(m)**if ~recs then append m to q, status := ?get(m)*~recr, m first on qtake first from q, if q now empty and status = ? then status := truegetAck(b)*~recs , status = bnonecrashs**recs := truecrashr**recr := truerecovers*recsrecs := falserecoverr*recrrecr := falseloserecs or recrdelete any element of q; if its the last then status := false or status := false Histories for AMO Messages ActionqstatusActionqstatusActionqstatusInitially< >trueput(red)?get(red)< >truegetAck(true)< >trueput(green)?crashr, lose?crashr, losefalsecrashr, lose< >false?getAck(false)falsegetAck(false)< >falseput(blue)?put( blue )< green ,  blue >?put( blue )< blue >?get( green )< blue >?get( green )< blue >?get( blue )< >truegetAck(true)< >true Channels State sr : multiset[P] := {} P = I M rs : multiset[P] := {} or I Bool NameGuardEffectNameGuardEffectsndsr(p)sr := sr {p}sndrs(p)rs := rs {p}rcvsr(p)p srsr := sr  {p}rcvrs(p)p rsrs := rs  {p}losesr$ p | p srsr := sr  {p}losers$ p | p rsrs := rs  {p} Stable Implementation State: modes : {acked, send, rec} := acked moder : {idle, rcvd, ack} := idle goods : set[ I ] := I goodr : set[ I ] := I lasts : I lastr : I cur : M buf : sequence[M] := <> NameGuardEffectNameGuardEffectput(m)** sndsr(i, m)*mode = acked and $ i | i good mode = send, i = last, m = curcur := m, last := i, mode := send, take i from good nonercvsr(i, m) **if i good then mode := rcvd, take i from good, last := i, append m to buf else if i = last and mode = idle then mode := ackget(m)*mode = rcvd, m first on buftake first from buf; if its now empty, mode := ackrcvrs(i, ) **if mode = send and i = last then mode := ackedsndrs(i, true)*mode = ack, i = lastmode := idlegetAck (true)*mode = ackednone What Does Implements Mean? Divide actions into external (marked * or **) and internal (unmarked). External actions change external state, internal ones dont. An external history is a history (sequence of actions) with all the internal actions removed. T implements S if every external history of T is an external history of S, and Ts liveness property implies Ss liveness property. Abstraction Functions Suppose we have a function f from Ts state to Ss state such that: f takes initial states to initial states; f maps every transition of T to a sequence of transitions of S, perhaps empty (i.e., the identity on S); f(t) S or skip f(t') t T t' f maps every external action of T to a sequence containing the same external action of S and no other external actions. f maps every internal action of T to a sequence of internal actions. Then T implements S. Why bother? Transitions are simpler than histories. Proof of Stable Implementation Invariants (1) goods ( {lasts} ids(sr) ids(rs) ) = {} (2) goodr ids(rs) = {} (3) goodr goods (4) ((i, m) sr and i goodr) implies m = cur Abstraction function q = <cur> if modes = send and lasts goodr < > otherwise + buf status = ? if modes = send true otherwise Methodology for Proofs Simplify the spec and the implementations. Save clever encodings for later. Make a  working spec that s easier to handle: It implements the actual spec. It has as much non-determinism as possible. All the prophecy is between it and the actual spec. actual implements working implements implemen- spec spec tation Find the abstraction function. The rest is automatic. Give names to important functions of your state variables. To design an implementation, first invent the guards you need, then figure out how to implement them. History Variables If you add a variable h to the state space such that If s is an old initial state then theres an h such that (s, h) is initial; If (s, h) (s', h') then s s'; If s s' then for any h there s an h' such that (s, h) (s', h') then the new state machine has the same histories as the old one. Predicting Non-Determinism Suppose we add mode := acked to crashs. Consider the sequence put( red ), snd, crashs, put( blue ), snd. Now we have sr = {(1,  red ), (2,  blue )}. We need an ordering on identifiers to order these packets and maintain fifo delivery. On rcvsr(i, m) the receiver must remove all identifiers d" i from goodr. But now  red is lost if (2,  blue ) is received first. If we use the obvious abstraction function q = the m s from {(i, m) sr (lasts, cur)| i goodr} sorted by i, this loss doesn t happen between crashs and recovers, as allowed by the spec, but later at the rcv. We give a working spec that makes this delay explicit. Delayed-Decision Specification State: q : sequence[(M, Flag)] := < > Flag = {OK, ?} status : ({true, false, ?}, Flag) := true recs/r : Boolean := false NameGuardEffectNameGuardEffectput(m)**if ~recs then add (m, OK) to q, status := (?, OK)get(m)*~recr, (m, ) first on qtake first from q, if q now empty and status = (?, f) status := (true, f)getAck(b)*~recs , status = (b, )nonemarkrecs or recrin some element of q or in status, set flag := ?unmarkin some element of q or in status, set flag := OKdroptruedelete some element of q with flag := ?, and if its the last, status := (false, OK) or if status = (, ?), status := (false, OK) Prophecy Variables If you add a variable p to the state space such that If s is an old initial state then theres a p such that (s, p) is initial; If (s, p) (s', p') then s s'; If s s' then for any h' there exists an h such that (s, h) (s', h') If s is an old state, there s a p such that (s, p) is a new state. then the new state machine has the same histories as the old one. If T implements S, you can always add history and prophecy variables to T and then find an abstraction function to S. Prophecy for Delayed-Decision Extend Flag to include a lost component drawn from the set {OK, lost}. The lost component prophesies whether drop will attack or not. The abstraction function is qS = the first components of elements of qDP that are not lost statusS = the first component of statusDP if it is not lost, else false. Delayed-Decision with Prophecy DP State: q : sequence[(M, Flag)] := < > Flag = ({OK, ?}, status : ({true, false, ?}, Flag) := (true, OK2) {OK, lost}) recs/r : Boolean := false NameGuardEffectNameGuardEffectput(m)**if ~recs then add (m,OK2) to q, status := (?, OK2)get(m)*~recr, (m, ) first on q and not losttake first from q, if q now empty and status = (?, f) status := (true, f)getAck(b)*~recs , status = (b, ), not lostnonemarkrecs or recr, $ x {OK, lost}in some element of q or in status, set flag := (?, x). If last of q is lost, set status flag (?, lost)unmarkin some element of q or in status that isn t lost, set flag := OKdroptruedelete some lost element of q or if status is lost, status := (false, OK2) Generic Implementation State: modes : {acked, send, rec} := acked moder : {idle, rcvd, ack} := idle goods : set[ I ] := {} goodr : set[ I ] := {} lasts : I lastr : I cur : M buf : sequence[M] := <> used : set[I] := {} nacks : sequence[I] := <> ack : Boolean := false NameGuardEffectNameGuardEffectput(m)** choose-id (i, m) sndsr(i, m)*mode = acked mode = needid, i good, m=cur as usualmode := needid, cur := m, good:={} mode := send, last := i, move i to from good to usedrcvsr(i, m) **if i good then mode := rcvd, take all Isd"i from good, last := i, append m to buf else if i `" last then add i to nacks else if i = last and mode = idle then mode := ackget(m)*as usualas usualrcvrs(i, b) **if mode = send and i = last then ack:=b mode := ackedsndrs(i,T) sndrs(i,F)mode = ack, i = last i first on nacksmode := idle take first from nacksgetAck(b)*mode = acked, b = acknone Generic Magic State: goods : set[ I ] := {} goodr : set[ I ] := {} lasts : I lastr : I useds : set[I] := {} issued : set[I] := {} NameGuardEffectNameGuardEffectshrink-gs(i) grow-gs(i)true i good, i usedtake i from good add i to good shrink-gr(i) grow-gr(i)i goods {lasts} i issuedtake i from good add i to good, issued cleanupmode `" rcvd, last `" lastslast := nilrecoversrecmode := acked, last := nil, ack := falserecoverrrecmode := idle, last := nil, take some Is from good, clear buf, nacks Generic Abstraction Function msg(id) = {m | (id = lasts and m=current ) or id ids(sr) or (id = lastr and m is last on buf)} This defines a partial function msg: ID M. current-q = <(current, OK)> if modes = send and lasts goodr or modes = needid and goods d" goodr <(current, ?)> if modes = needid and not goods d" goodr <> otherwise inflightsr = {id | id ids(sr) and id goodr and not (id = lasts and modes = send) }, sorted by id to make a sequence inflight-m = the sequence of Ms gotten from msg of each I in inflightrs. inflightrs = {lasts} if (ack, lasts, true) rs and not lasts = lastr Generic Abstraction Function queue the elements of bufr paired with OK+ the elements of inflight-m paired with ?+ current-qstatus (false, OK) if modes = rec else (?, f) if current-q = <(m, f)> (?, OK) if modes = send, lasts = lastr and buf `" empty (true, OK) if modes = send, lasts = lastr and buf = empty (true, ?) if modes = send and lasts inflightrs (false, OK) if modes = send and lasts (goodr {lastr} inflightrs) (ack, OK) if modes = acked Practical Implementations Generic Five-packet handshakeLiskov-Shrira-Wroclawskigoods{id | (accept, jds, id) rs} if mode = needid {} otherwise{times}  {lasts}goodr {lastr} if moder = accept {} otherwise{i | lower < i and (i upper or moder = rec) }lastr lastr if mode `" accept nil otherwiselastr  shrink-goodsmode = needid and losers(accept, jds, id) of last copy or receivers(accept, jds, id), ids = goods  {id}tick(id), id = timesgrow-goodssendrs(accept, jds, id)tick(id) cleanupreceivesr(acked), mode = ackcleanupshrink-goodrmode = accept and receivesr(acked, idr, nil)increase-lower(id), ids = {i | lower < i d" id}grow-goodrmode = idle and receivesr(needid, ...),increase-upper(id), ids = {i | upper < i d" id} Summary Client specification of at-most-once messages. Working spec which maximizes non-determinism. Generic implementation with good identifiers maintained by magic. Two practical implementations Five-packet handshake Liskov-Shrira-Wrowclawski To follow up ... You can find these slides on research.microsoft.com/lampson, as well as a paper (item 47 in the list of publications). L. Lamport, A simple approach to specifying concurrent systems, Comm. acm 32, 1, Jan. 1989. M. Abadi and L. Lamport, The existence of refinement mappings, DEC SRC research report 29, Aug. 1988. Understanding Network Connections October 30, 1995 "tuR N O % &   I O TWXY\_`adijmtpq@BXZlx068:@BVXz|DEQR\bf 6CJ$EH6:5CJCJ(CJ8]"12 #$It~ E R N Z + &h^h$9$a$LYY+ % 1  @ Fkpf0 @ P] d]d ^ =D$$IfP40`:L4 Pa 5$$Ifa$   @ P fqy}   $'(*+567GHMN_erx|6EHCJ$OJQJ 6CJEH5 6CJ$EH6Z#7o|iiiiiioiiii5$If$$IfP4ֈ`#/:X  |@  4 Pa ii$$IfP4ֈ`#/:X  |@  4 Pa5$If %{|}~i$$IfP4ֈ`#/:X  |@  4 Pa5$If   #$=>X^bgkquz~#$(.3:=RSZ_`bfrxy{5CJCJ$6OJQJ 6CJEH\~okeeeeeeeee5$If$$IfP4ֈ`#/:X  |@  4 Pa 6h00005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa5$If6p00005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa5$If 6l00005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa5$If*.346t00005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa4567895$If9:GQST600005$If$$IfP4 l"H&.59\p.p.H:$$$$4 PaTUVWXY5$IfYZgqs6800005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa5$If600005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa5$If 6h00005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa HP`bvxz&(024<HJNPRTVtx468:H 6CJEH5OJQJCJ6^ FJbtx5$Ifxz600005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa5$If 6p00005$If$$IfP4 l"H&.59\p.p.H:$$$$4 Pa5$If4<FH6t00005$If$$IfP4 l"H&.59\p.p.H:$$$$4 PaHJLNPR5$IfRThHR620$ 5$d$Ifa$6$$IfP4 l"H&.59\p.p.H:$$$$4 PaR^lvc]]]]5$If$$IfP4ֈ`#-:X  |$  4 Pa 5$d$Ifa$  6HVti$$IfP4ֈ`#-:X  |$  4 Pa5$If  $(026<@BDFJLNPTVZbfnpv~ $%)9>CDHI6EHCJ 6CJEHOJQJ6]tvoiiiiiioe5$If$$IfP4ֈ`#-:X  |$  4 Pa IM\aegkltu{    (.6:JNPV\^dlzOJQJ5 6CJEH6EH6]Q$$IfP4ֈ`#-:X  |$  4 Pa 5$d$Ifa$6 &0$ (3] ^ip$$IfP4ֈ`#&:X  |4 Pa5$If  &.68:DFRZdltv #&'7:OSWZ\_abcklosvz 6CJEH 6OJQJCJ$6OJQJ\ '[\kla$$IfP4ֈ`#-:X  |$  4 Pa5$If5$If oiiiiiioe_d]d5$If$$IfP4ֈ`#-:X  |$  4 Pa (0FN  $ % @ A G H e f | } !!!!>!?!f!g!k!l!m!n!q!u!v!"""" """"&"("0"2"4"H"J"d"f"j"p"r"t""" #"#b#d#####$$$$$$$$$$ 6CJ$EHOJQJ EHOJQJ6>*>*CJCJ$6X G | !j!,"."r"b##$$$8%j%%%&&^ t h^ P^ t hP^ P $$$%%%%%%"%&%>%H%J%L%N%X%\%p%z%|%~%%%%%%%%%%%%%%%%%%%%%%&&&&,&6&>&@&F&N&X&`&b&d&f&h&p&r&v&&&&&&&&&&&&''6'F'2)>)@)J)^)h)j)x)z)))>*CJ$ 5>*CJ$5EHOJQJ5CJOJQJ 6CJ$EH6V&'6''2)).*d**++M++0,,:-r--D./0.1122R2  d^x^x^))))**%*-*++.+/+P+Q+z+{+++++,,,, ,",$,&,(,,,6,8,:,<,>,B,^,`,x,|,,,,,,,:-<----------. .... .&.:.@.\.`.*/2/N/T/X/Z/b//////000000000000: 6CJ$EHOJQJ6CJ5 5>*CJ$[0000000111 11&1(1p1z1|1111112232Y2Z2g2n2|22222222222222222222222333333 3%3+3335373:3;3<3@3C3D3H3I3W3X3Y3i3j3o3p33333333333333CJ$ 6CJEH5CJOJQJ 6CJ$EH6ZR22222222223]WW5$If$$IfP4ֈ`#/:X  |@  4 Pa 5$$Ifa$  < 373?3Y3333333333ii$$IfP4ֈ`#/:X  |@  4 Pa5$If 33333333333333333334 4444 45464=4C4I4M4Q4S4T4U4_4v4w4}4444444444444444557585`5a5m5q5556666 6"6$6&6(6,66686:6<6>6B6^6b6666666666677OJQJCJCJ$ 6CJEH6]3334!4"4T4U4Z4_4444iX$$IfP4ֈ`#/:X  |@  4 Pa5$If 4444455066F77[8z8iecaaaacce $$IfP4ֈ-./:X l 4 Pa5$If 77"77777-8.8X8Y8[8\88888888888999F9G9I9\9c9d9~9999999999999999: :::!:%:+:3:5:;:C:G:J:M:[:`:a::::::::::::::::::::::CJEH 6CJEH5 6CJ$EHCJ$EHCJEHCJEHCJ6Uz8899\9999a:f:l:s:x:~:: 5$$Ifa$  <]:::::::E;F;Q;x;};~;oiiiiiioiiii5$If$$IfP4ֈ`#/:X  |@  4 Pa :::::::::::;; ; ;;#;*;+;1;7;<;C;E;F;L;M;N;R;U;V;Y;_;h;i;;;;;;;;;;<<<<< <<<H<J<X<d<p<x<<<<<<<<<<<&=(=6=B=p=x==========> >>>>>>>>CJCJEHCJ$OJQJ 6CJEH6[~;;;;;"<<<==i\$$IfP4ֈ`#/:X  |@  4 Pa5$If ====>>>>ohiiiiii5$If$$IfP4ֈ`#/:X  |@  4 Pa>>6>2?7?=?D?I?O?okVJJJJJ 5$d$Ifa$6 &0$ (3dp]$$IfP4ֈ-./:X l 4 Pa>=>A>B>F>V>[>`>a>e>f>j>y>~>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>??????,?1?2?V?W?Z?[?]?a?k?l?q?r?u?w?x?|??????????@@@ @@@@@.@6@>@J@L@T@\@OJQJ5 6CJEH6EH6]O?V?W?a?r???@.@t@@c]]]]]]]]5$If$$IfP4ֈ`#-:X  |$  4 Pa 5$d$Ifa$ \@^@b@j@r@|@@@@@@@@@@@@@@@@@@@@@AAA A AA(A0A8A@ABADAVAXA\A^ApAxA|AAAAAAAAAAAAAAAABB BBBBBB'B+B/B2B3B4B6B7B:B;BGJGNGPGRG\G`GGGGGGGGGG,H0H2H4H6H8HMPMTM`MhMzMMMMMMMMMMMMMMMN 6CJEH6EHCJOJQJ 6CJ$EH6ZLLLLL6M8M:MRMTMbMM8n`b 5 @ $IfD$$IfP40.)4 PaF$$IfP40)x#4 Pa5$If MMTNN.OOPP:PLPxPP5$IfD$$IfP40.)4 Pa 5 @ $If NN NNN N"N(N0N2NRRRRRRSSS`5$IfW$$IfP4F<$9T    4 PaPPPPPPQQQ8Q@QBQLQTQVQXQZQ\QdQfQhQjQlQtQvQQQQQQQQQQQQQQQQQRRRR R&R0R8R:R*CJOJQJkHRR Heading 5,5&$hd]^`ha$CJRR Heading 6,6&$hd]^`ha$CJBB Heading 7 ^6CJOJQJkHNN Heading 8&$@ hd]^@ `ha$CJB B Heading 9 ^6CJOJQJkH<A@< Default Paragraph Font22 TOC 3 X !^22 TOC 2 X !^** Index 6 ^** Index 5 ^* * Index 4 8^8* * Index 3 ^* * Index 2 h^h" " Index 1&(@q& Line Number, , Footer  !,, Header  !<&@< Footnote ReferenceCJEH22 Footnote TextCJ&)@& Page Number(( points ^00 ex^ OJQJkH** ex1  H]H$O$ in ^"" in1 ! 0"0 in2" LP]P.2. in3#x 8 l$B$ in4 $ DRD ie)%$  0hd]0`ha$CJ88 cont&$dP]a$CJTrT Glossary entry"'$hd<]`ha$CJJJ Reference"($hdx]`ha$CJNN pub2)$ dx]^`a$CJVV type,*$ X|hd]|`ha$CJOJQJkHDD ax*+$ !dP]^CJFF ref*,$hd$]^h`a$CJ88 gr- $ ]^CJ@@ pic#.$$"F]a$CJ:: lin/$dPP]a$CJ"" cap0$CJ lax1P:: fnormal2$d]a$CJ 2 tcap36B6 tab4$$d]CJ(OR( t5dp]CJ$>Ob> state6 $&0CJ$DD sig'7$Hd(]^`HCJ>> pf#8$ d$(]CJ:B@: Body Text9x]CJs:  #7%{|}~ *.3456789:GQSTUVWXYZgqs#%1:<=JSUbkmnopq}IRSbkl{| )I%Auv  .7Y7"@"A"x""""""#######*#[#b#c#####($)$*$+$,$@$$$P(Y(Z(((()))B)G)H)I)J)K)P)o))))!*"*'*,*x*y*z*{*|**+++++ ,,6,k,z,{,/-0-1-2-3-;-D-M-N-]-^---------... .!.".#.2.....//"/0/;/U/`/r///////////////C0D0b0^3_3333333334T44444 5E5K55555566666=6>6?66666677&7'747a7777777;:p:t:505050505050050505050505005050505050500505050505050050505050505005050505050500 050505050505050505005050505050505050500505050505050505050050505050505050505005050505050505050500505050505050505050050505050505050505005050505050505050500505050505050505050050505050505050505005050505050505050500 0505050505050050505050505005050505050500 05050505050505050500505050505050050505050505005050505050500 0 0 05050505050500505050505050050505050505005050505050500 0 05050505050500505050505050050505050505005050505050500 050505050505050505050500505050505050050505050505050505005050505050500 0505050505050505050505050050505050505005050505050500 0505005050050505050505050500 050505005050500505050005050500505050050505005050500@0 6669fI$)037:>\@lBCFINPSXY5:>OZ\_bdfgjmptvy|+ ~49TY xHRRt&R2334z8:~;=>O?@QBCCC:EFLMPSVY689;<=?@ABCDEFGHIJKLMNPQRSTUVWXY[]^`acehiklnoqrsuwxz{}~Y7!* , - f g k l  $' ##"INSUY[bglnrt|).69>CY\ !78[\st=@QTqtv{|}%'/1JLklsuz{qzpxDG^aoq 7!:!!!E"H"""""""# #%#(#((^(a(n(r((())))P)S)X)[)********0+3+^+c+y+|+++++++++++++,!,L,M,T,U,k,p,q,r,~,,,,,,,,,,,,,,--+-.-N-S-T-U-q-r------------------------- ............////,/-/8/9/;/BW[kl7={56 8< !!!!7":"A"C"x"{"""""""""##### #*#,#[#a#c#e#######$$m%q%&&''-'''P(S(Z(\((((((())))B)F)K)O)P)S)o)q)))))))"*&*'*+*,*2***++++++++++ , ,,,6,:,k,n,{,},3-6-;-=-D-F-N-Q-^-`---------------....>.@.........////"/(/0/4/;/6?6L6666666677&7'747a7777777;:q:t:@Acrobat PDFWriterLPT1:Acrobat PDFWriterAcrobat PDFWriterAcrobat PDFWriter d od,,Acrobat PDFWriter d od,,w9w9lw99t". AAA A!$%^)^*+,./012345678s:@$@4@<@"$&(T@,.0d@6p@<|@@@DFHJLNPRTV@UnknownG:Times New Roman5Symbol3& :ArialY New YorkTimes New RomanO1CourierCourier New"6;5 l0fY;0d:;!Understanding Network ConnectionsButler LampsonButler Lampson Oh+'0 ,8 T ` lx"Understanding Network ConnectionsosndeButler Lampsoneutlutl Normal.dotsButler Lampsone6tlMicrosoft Word 9.0r@vA@3b@=7bl0 ՜.+,0 px   sf: "Understanding Network Connections Title  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry JF\H FJNOEb1Table55eJ<@JDJ_WordDocument07<@SummaryInformationa(% JDocumentSummaryInformation8,@CompObjDJTJJ% jObjectPoolOEbOEb5GJ<@ZHسJ 0  FMicrosoft Word Document MSWordDocWord.Document.89q