電腦網路
Computer Networks
Chapter 3:
Transport Layer
http://www.cyut.edu.tw/~hcchu
Computer Networking: A Top Down Approach ,
4thedition.
Jim Kurose, Keith Ross Addison-Wesley, July 2007.
Outline
3.1 Transport-layer services
3.2 Multiplexing and demultiplexing
3.3 Connectionless transport: UDP
3.4 Principles of reliable data transfer
3.5 Connection-oriented transport: TCP
segment structure
reliable data transfer
flow control
connection management
3.6 Principles of congestion control
3.7 TCP congestion control
3.1 Transport-layer services
傳輸層服務
Transport services and protocols
Provide logical communication between app processes running on different hosts
提供不同主機上執行應用程式之間的邏輯通訊
Transport protocols run in end systems 在終端系統間執行的傳輸協定
Send side: breaks app messages into segments,
passes to network layer 傳送端: 將應用程式的訊息 分割成資料分段、傳送到網路層
Rcv side: reassembles segments into messages, passes to app layer
接收端: 將資料分段重組成訊息、傳給應用層
More than one transport protocol available to apps 應用層可用的傳輸協定超過一個
Internet: TCP and UDP
application transport
network data link physical
application transport
network data link physical
logical end-e
nd tran sport
Transport vs. Network layer 傳輸 vs. 網路層
Network layer: logical communication between hosts
網路層:主機之間的邏輯通訊
Transport layer: logical
communication between processes 傳輸層:行程之間的邏輯通訊
Relies on, enhances, network layer services 依賴、 增強、 網路層服務
Internet transport-layer protocols 網際網路傳輸層協定
Reliable, in-order delivery (TCP)
可靠的、 有序的遞送
Congestion control壅塞控制
Flow control流量控制
Connection setup連線建立
Unreliable, unordered delivery: UDP
不可靠的、 無序的遞送
No-frills extension of “best-effort” IP
“盡全力”的 IP的精簡延伸
application transport
network data link physical
network data link physical
network data link physical network
data link physical
network data link physical network
data link physical
network data link physical
application transport
network data link physical
logical end -end t
ransport
3.2 Multiplexing and
demultiplexing 多工和解多工
Multiplexing/demultiplexing
application transport network link
physical
P1 application
transport network link physical application
transport network
link physical
P3 P1 P2 P4
host 1 host 2 host 3
= process
= socket
Delivering received segments to correct socket
Demultiplexing at rcv host:
Gathering data from multiple sockets, enveloping data with header (later used for
demultiplexing)
Multiplexing at send host:
多工/解多工
應用層 傳輸層 網路層 資料連結層 實體層
P1 應用層
傳輸層 網路層 資料連結層 實體層 應用層
傳輸層 網路層 資料連結層
實體層
P3 P1 P2 P4
主機 1 主機 2 主機 3
= 行程
= socket
將收到的資料分段 傳送給正確的socket
接收端主機的解多工:
收集多個socket的資料、
用標頭 (稍後將用在解多工) 將每個資料片段封裝成
資料分段
傳送端主機的多工:
How demultiplexing works 解多工如何運作
Host receives IP datagrams 主機收到 IP 資料段
Each datagram has source IP address, destination IP address
每一個資料段都擁有來源端 IP位址以及 目的端IP位址
Each datagram carries 1 transport-layer segment
每一個資料段載送 1 個傳輸層資料分段
Each segment has source, destination port number
每一個資料分段都擁有來源端以及目的 端埠號
Host uses IP addresses & port numbers to direct segment to appropriate socket主機使用 IP 位址 以及埠號將資料分段送到正確的socket
source port # dest port # 32 bits
application data (message)
other header fields
TCP/UDP segment format
Connectionless demultiplexing
無連線的解多工
Create sockets with port numbers:
以埠號產生socket
DatagramSocket mySocket1 = new DatagramSocket(12534);
DatagramSocket mySocket2 = new DatagramSocket(12535);
UDP socket identified by two-tuple:
以兩組資料識別 UDP socket
(dest IP address, dest port number)
When host receives UDP segment: 當主機收到 UDP 資 料分段時
Checks destination port number in segment確認資料分段中的來源 端埠號
Directs UDP segment to socket with that port number以此埠號將 UDP資料分段傳送到socket
IP datagrams with different source IP
addresses and/or source port numbers directed to same socket 具有不同來源端 IP 位址的IP 資料段 和/或 來源 端埠號會被送到同一個 socket
Connectionless demux (cont)
DatagramSocket serverSocket = new DatagramSocket(6428);
Client
IP:B P2
client IP: A
P3 P1P1
server IP: C
SP: 6428 DP: 9157 SP: 9157
DP: 6428
SP: 6428 DP: 5775
SP: 5775 DP: 6428
SP provides “return address”
SP: Source Port DP: Dest. Port
Connection-oriented demux
TCP socket identified by 4-tuple:
TCP socket 以四組資料加以識別
source IP address 來源端 IP 位址
source port number 來源端埠號
dest IP address 目的端 IP 位址
dest port number 目的端埠號
Recv host uses all four values to
direct segment to appropriate socket
接收端主機使用全部的四個數值將資料分段送到
適當的 socket
Server host may support many simultaneous TCP sockets:
伺服端主機可能同時支援許多TCP sockets
Each socket identified by its own 4-tuple 每個 socket 以它自己的四組資料加以識別
Web servers have different sockets for each connecting client
Web 伺服器針對連結到它的每一個用戶端都有 不同的socket
Non-persistent HTTP will have different socket for each request
非永久性 HTTP 針對每一次的請求都有不同的 socket
Connection-oriented demux (cont)
Client
IP:B P1
client IP: A
P2 P1 P4
server IP: C
SP: 9157 DP: 80
SP: 9157 DP: 80
P5 P6 P3
D-IP:C S-IP: A
D-IP:C
S-IP: B SP: 5775
DP: 80 D-IP:C S-IP: B
Connection-oriented demux:
Threaded Web Server
Client
IP:B P1
client IP: A
P2 P1
server IP: C
SP: 9157 DP: 80
SP: 9157 DP: 80
P4 P3
D-IP:C S-IP: A
D-IP:C
S-IP: B SP: 5775
DP: 80 D-IP:C S-IP: B
3.3 Connectionless transport:
UDP 無傳輸連線UDP
UDP: User Datagram Protocol
[RFC 768]
“No frills,” “bare bones” Internet transport protocol 實際的、精簡的網際網路傳輸協定
“Best effort” service, UDP segments may be:
“盡全力” 的服務、 UDP 資料分段可能
Lost遺失
Delivered out of order to app不按順序傳送給應用程式
Connectionless:非預接式服務
No handshaking between UDP sender, receiver 在 UDP 傳送端和接收單之間沒有交握程序
Each UDP segment handled independently of others 每一個 UDP 資料分段的處理和其它資料分段是獨立的
Why is there a UDP?
為什麼會使用 UDP?
No connection establishment (which can add delay)
不需建立連線 (會增加延遲)
Simple: no connection state at sender, receiver
簡單: 在傳送端和接收端不需維持連線狀態
Small segment header較小的封包標頭
No congestion control: UDP can blast away as fast as desired
沒有壅塞控制: UDP 可以僅可能地快速傳送資料
UDP: more
Often used for streaming multimedia apps
通常用在串流的多媒體應用程式
Loss tolerant可以容忍遺失
Rate sensitive易受速率影響
Other UDP uses 其他使用 UDP 的有
DNS
SNMP
Reliable transfer over UDP: add reliability at application layer 使用UDP的可靠傳輸: 在應用層加入可 靠性的機制
Application-specific error recovery!
應用層指定的錯誤復原
source port # dest port # 32 bits
Application data (message)
UDP segment format length checksum Length, in
bytes of UDP segment, including header
UDP checksum檢查和
Sender:
Treat segment contents as sequence of 16-bit
integers
將資料分段的內容視為一列16位 元的整數
Checksum: addition (1’s complement sum) of
segment contents檢查和:
資料分段內容的加法 (1的補數和)
Sender puts checksum value into UDP checksum field傳送端將檢查和的值放入 UDP的檢查和欄位
Receiver:
Compute checksum of
received segment計算收到的 資料分段的檢查和
Check if computed checksum equals
checksum field value:確認計 算出來的檢查和是否和檢查和欄位 中的相等
NO - error detected偵測到錯誤
YES - no error detected. But
maybe errors nonetheless?沒有偵
Goal: detect “errors” (e.g., flipped bits) in transmitted segment
目標: 偵測傳送的資料分段中的 “錯誤” (例如:被翻轉的位元)
Internet Checksum Example網際 網路的檢查和範例
Note
When adding numbers, a carryout from the most significant bit needs to be added to the result
當數字加總時、最高位元的進位必須被加回結果中
Example: add two 16-bit integers 加總兩個 16 位元的整數
1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 Wraparound
繞回去
sum checksum
3.4 Principles of reliable data
transfer可靠資料傳輸的原理
Principles of Reliable data transfer可靠資料傳輸的原理
Important in app., transport, link layers
在應用層、傳輸層、資料連結層 中都是很重要的
Characteristics of
unreliable channel will determine complexity of reliable data transfer
protocol (rdt)
不可靠通道的特性決定了可靠資 料傳輸協定 (rdt) 的複雜性
Reliable data transfer: getting started
sendside receive
side
rdt_send(): called from above, (e.g., by app.). Passed data to deliver to receiver upper layer
udt_send(): called by rdt, to transfer packet over unreliable channel to receiver
rdt_rcv(): called when packet arrives on rcv-side of channel deliver_data(): called by
rdt to deliver data to upper
可靠的資料傳輸: 開始
sendside receive
side
rdt_send(): 被上層呼叫、 (例如 應用層). 將資料傳遞給接收端的上層
協定
udt_send(): 被rdt呼叫、
經由不可靠的通道將封包傳送給 接收端
rdt_rcv(): 當封包抵達接收端的 通道時被呼叫
deliver_data(): 被 rdt 呼 叫、將資料傳送到上層
參考內容(不考)
pp. 30-64
Reliable data transfer: getting started
We’ll:
Incrementally develop sender, receiver sides of reliable data transfer protocol (rdt)
Consider only unidirectional data transfer
But control info will flow on both directions!
Use finite state machines (FSM) to specify sender, receiver
state
1 state
2 event causing state transition
actions taken on state transition State: when in this
“state” next state uniquely determined by next event
event actions
Rdt1.0: reliable transfer over a reliable channel
Underlying channel perfectly reliable
No bit errors
No loss of packets
Separate FSMs for sender, receiver:
Sender sends data into underlying channel
Receiver read data from underlying channel
Wait for call from
above packet = make_pkt(data) udt_send(packet)
rdt_send(data)
extract (packet,data) deliver_data(data) Wait for
call from below
rdt_rcv(packet)
sender receiver
Rdt2.0: channel with bit errors
Underlying channel may flip bits in packet
Checksum to detect bit errors
The question: how to recover from errors:
Acknowledgements (ACKs): receiver explicitly tells sender that pkt received OK
Negative acknowledgements (NAKs): receiver explicitly tells sender that pkt had errors
Sender retransmits pkt on receipt of NAK
New mechanisms in rdt2.0 (beyond rdt1.0):
Error detection
Receiver feedback: control msgs (ACK,NAK) rcvr->sender
rdt2.0: FSM specification
Wait for call from
above
snkpkt = make_pkt(data, checksum) udt_send(sndpkt)
extract(rcvpkt,data) deliver_data(data) udt_send(ACK) rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
udt_send(NAK) rdt_rcv(rcvpkt) &&
corrupt(rcvpkt) Wait for
ACK or NAK
Wait for call from
below
sender
receiver
rdt_send(data)
Λ
rdt2.0: operation with no errors
Wait for call from
above
snkpkt = make_pkt(data, checksum) udt_send(sndpkt)
extract(rcvpkt,data) deliver_data(data) udt_send(ACK) rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
udt_send(NAK) rdt_rcv(rcvpkt) &&
corrupt(rcvpkt) Wait for
ACK or NAK
Wait for call from
below rdt_send(data)
Λ
rdt2.0: error scenario
Wait for call from
above
snkpkt = make_pkt(data, checksum) udt_send(sndpkt)
extract(rcvpkt,data) deliver_data(data) udt_send(ACK) rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
udt_send(NAK) rdt_rcv(rcvpkt) &&
corrupt(rcvpkt) Wait for
ACK or NAK
Wait for call from
below rdt_send(data)
Λ
rdt2.0 has a fatal flaw!
What happens if ACK/NAK
corrupted?
Sender doesn’t know what
happened at receiver!
Can’t just
retransmit: possible duplicate
Handling duplicates:
Sender retransmits current pkt if
ACK/NAK garbled
Sender adds sequence number to each pkt
Receiver discards (doesn’t deliver up) duplicate pkt
Sender sends one packet, then waits for receiver response
stop and wait
rdt2.1: sender, handles garbled ACK/NAKs
Wait for call 0 from
above
sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt)
rdt_send(data)
Wait for ACK or
NAK 0 udt_send(sndpkt) rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isNAK(rcvpkt) )
sndpkt = make_pkt(1, data, checksum) udt_send(sndpkt)
rdt_send(data)
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isNAK(rcvpkt) ) rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)
Wait for call 1 from
above Wait for
ACK or NAK 1
Λ Λ
rdt2.1: receiver, handles garbled ACK/NAKs
Wait for 0 from
below
sndpkt = make_pkt(NAK, chksum) udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq0(rcvpkt)
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt) extract(rcvpkt,data) deliver_data(data)
sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt)
Wait for 1 from
below
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq0(rcvpkt) extract(rcvpkt,data) deliver_data(data)
sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq1(rcvpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt)
sndpkt = make_pkt(NAK, chksum) udt_send(sndpkt)
rdt2.1: discussion
Sender:
Seq # added to pkt
Two seq. #’s (0,1) will suffice. Why?
Must check if
received ACK/NAK corrupted
Twice as many states
State must “remember”
whether “current” pkt has 0 or 1 seq. #
Receiver:
Must check if
received packet is duplicate
State indicates whether 0 or 1 is expected pkt seq #
Note: receiver can not know if its last ACK/NAK received OK at sender
rdt2.2: a NAK-free protocol
Same functionality as rdt2.1, using ACKs only
Instead of NAK, receiver sends ACK for last pkt received OK
Receiver must explicitly include seq # of pkt being ACKed
Duplicate ACK at sender results in same action as NAK: retransmit current pkt
rdt2.2: sender, receiver fragments
Wait for call 0 from
above
sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt)
rdt_send(data)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,1) )
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,0)
Wait for ACK
sender FSM 0
fragment
Wait for 0 from
below
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt) extract(rcvpkt,data) deliver_data(data)
sndpkt = make_pkt(ACK1, chksum) udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
(corrupt(rcvpkt) ||
has_seq1(rcvpkt)) udt_send(sndpkt)
receiver FSM fragment
Λ
rdt3.0: channels with errors and loss New assumption:
underlying channel can also lose
packets (data or ACKs)
Checksum, seq. #, ACKs, retransmissions will be of help, but not enough
Approach: sender waits “reasonable”
amount of time for ACK
Retransmits if no ACK received in this time
If pkt (or ACK) just delayed (not lost):
Retransmission will be duplicate, but use of seq.
#’s already handles this
Receiver must specify seq
# of pkt being ACKed
Requires countdown timer
rdt3.0 sender
sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt)
start_timer rdt_send(data)
Wait for ACK0
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,1) )
Wait for call 1 from
above
sndpkt = make_pkt(1, data, checksum) udt_send(sndpkt)
start_timer rdt_send(data)
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,0)
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,0) ) rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,1)
stop_timer stop_timer
udt_send(sndpkt) start_timer
timeout
udt_send(sndpkt) start_timer
timeout
rdt_rcv(rcvpkt)
Wait for call 0from
above
Wait for ACK1
Λ
rdt_rcv(rcvpkt)
Λ Λ
Λ
rdt3.0 in action
rdt3.0 in action
Performance of rdt3.0
rdt3.0 works, but performance stinks
Example: 1 Gbps link, 15 ms e-e prop. delay, 1KB packet:
Ttransmit = 8kb/pkt
10**9 b/sec = 8 microsec
U sender: utilization – fraction of time sender busy sending
U sender = .008
30.008 = 0.00027 L / R
RTT + L / R = L (packet length in bits)
R (transmission rate, bps) =
1KB pkt every 30 msec -> 33kB/sec thruput over 1 Gbps link
Network protocol limits use of physical resources!
rdt3.0: stop-and-wait operation
first packet bit transmitted, t = 0
sender receiver
RTT last packet bit transmitted, t = L / R
first packet bit arrives
last packet bit arrives, send ACK
ACK arrives, send next packet, t = RTT + L / R
U sender = .008
30.008 = 0.00027 L / R
RTT + L / R =
可靠的資料傳輸: 開始
我們將會:
漸進式地建立傳送端、接收端的可靠資料傳輸協定 (rdt)
只探討單向的資料傳輸
但是控制資訊會在雙向流動!
使用有限狀態機 (FSM)指定傳送端、 接收端
狀態1 狀態
2 導致狀態轉換的事件
狀態轉換時所採取的動作 狀態: 在這個”狀態”時、
下一個狀態將唯一地
被下一個事件所決定 事件
動作
Rdt1.0: 使用可靠通道的可靠傳輸
底層的通道是完全可靠的
沒有位元錯誤
沒有資料遺失
傳送端和接收端擁有各自的 FSM:
傳送端將資料送入底層的通道
接收端從底層的通道接收資料
等待上層 傳來的呼
叫 packet = make_pkt(data) udt_send(packet)
rdt_send(data)
extract (packet、data) deliver_data(data) 等待下層
傳來的呼 叫
rdt_rcv(packet)
傳送端 接收端
Rdt2.0: 可能產生位元錯誤的通道
底層的通道可能會將封包中的位元翻轉
偵測位元錯誤的檢查和
問題: 如何回復錯誤:
確認 (ACKs): 接收端明確地告訴傳送端封包的傳送 OK
否定確認 (NAKs): 接收端明確地告訴傳送端封包的傳送有問 題
當收到NAK時、傳送端會重傳封包
rdt2.0 的新機制 (超出rdt1.0):
錯誤偵測
接收端回饋: 控制訊息 (ACK、NAK) 接收端->傳送端
rdt2.0: FSM 說明
等到從上 層傳來的
呼叫
snkpkt = make_pkt(data、 checksum) udt_send(sndpkt)
extract(rcvpkt、data) deliver_data(data) udt_send(ACK) rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
udt_send(NAK) rdt_rcv(rcvpkt) &&
corrupt(rcvpkt) 等待ACK
或者NAK 訊息
等待從下 層傳來的
傳送端 呼叫
接收端
rdt_send(data)
Λ
rdt2.0: 沒有錯誤時的運作
Wait for call from
above
snkpkt = make_pkt(data、 checksum) udt_send(sndpkt)
extract(rcvpkt、data) deliver_data(data) udt_send(ACK) rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
udt_send(NAK) rdt_rcv(rcvpkt) &&
corrupt(rcvpkt) Wait for
ACK or NAK
Wait for call from
below rdt_send(data)
Λ
rdt2.0: 發生錯誤的情況
Wait for call from
above
snkpkt = make_pkt(data、 checksum) udt_send(sndpkt)
extract(rcvpkt、data) deliver_data(data) udt_send(ACK) rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
udt_send(NAK) rdt_rcv(rcvpkt) &&
corrupt(rcvpkt) Wait for
ACK or NAK
Wait for call from
below rdt_send(data)
Λ
rdt2.0 有一個致命的缺點!
假如 ACK/NAK 損毀了會 如何?
傳送端不知道接收端發生了什 麼事!
沒辦法直接重傳: 可能會重複
重複的處理:
假如 ACK/NAK損壞了、傳送 端會重新傳送目前的封包
傳送端會在每個封包加上序號
接收端或刪掉 (不往上傳) 重複 的封包
傳送端傳送一個封包、
並等待接收端的回應
停止以及等待
rdt2.1: 傳送端、 處理損毀的 ACK/NAK
等待從上 一層傳來 的呼叫0
sndpkt = make_pkt(0、 data、
checksum)
udt_send(sndpkt) rdt_send(data)
等待ACK 或NAK訊
息0 udt_send(sndpkt) rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isNAK(rcvpkt) )
sndpkt = make_pkt(1、 data、
checksum)
udt_send(sndpkt) rdt_send(data)
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isNAK(rcvpkt) ) rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)
等待從上 一層傳來 的呼叫1 等待ACK
或NAK訊 息1
Λ Λ
rdt2.1: 接收端、 處理損毀的 ACK/NAK
等待從 下層傳 來的0
sndpkt = make_pkt(NAK、 chksum) udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq0(rcvpkt)
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt) extract(rcvpkt、data) deliver_data(data)
sndpkt = make_pkt(ACK、 chksum) udt_send(sndpkt)
等待從 下層傳 來的1
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq0(rcvpkt) extract(rcvpkt、data) deliver_data(data)
sndpkt = make_pkt(ACK、 chksum) udt_send(sndpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
sndpkt = make_pkt(ACK、
chksum)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq1(rcvpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
sndpkt = make_pkt(ACK、
chksum)
udt_send(sndpkt)
sndpkt = make_pkt(NAK、 chksum) udt_send(sndpkt)
rdt2.1: 討論
傳送端:
在封包加入序號
兩個序號 (0、1) 就足夠 了。為什麼 ?
必須檢查收到的
ACK/NAK 是否損毀
兩倍數量的狀態
狀態必須”記得” “目前的”封 包序號為 0 或是 1
接收端:
必須確認接收端封包是否 重複
狀態表示 0 或 1 是否為所預 期的封包序號
注意: 接收端無法得知它 的最後一個 ACK/NAK 是否在傳送端被接收無誤
rdt2.2: 不採用NAK訊息的協定
與 rdt2.1 同樣的功能、但只使用ACK
不使用NAK、 接收端傳送 ACK 表示最後一個封包接收 正確
接收端必須明確地加上經過確認封包的序號
在傳送端收到重複的 ACK 導致與 NAK 相同的行為:
重新傳送目前的封包
rdt2.2: 傳送端、 接收端片段
等待從上 層傳來的
呼叫0
sndpkt = make_pkt(0、 data、
checksum)
udt_send(sndpkt) rdt_send(data)
udt_send(sndpkt) rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt、1) )
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt、0)
等待 ACK0
傳送端 FSM 片段
等待從 下層傳 來的呼
叫0
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt) extract(rcvpkt、data) deliver_data(data)
sndpkt = make_pkt(ACK1、 chksum) udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
(corrupt(rcvpkt) ||
has_seq1(rcvpkt)) udt_send(sndpkt)
接收端 FSM 片段
Λ
rdt3.0: 使用會發生錯誤及遺失封 包的通道
新的假設: 底層的頻道也可 能遺失封包 (資料或
ACK)
檢查和、 序號、 ACK、 重 傳都是有幫助的、但是卻不 夠
方法: 傳送端等待ACK “合 理的” 時間
假如在這段時間內沒有收到 ACK、則重傳
假如封包 (或 ACK) 只是延遲 了 (沒有遺失):
重傳會導致重複、但是序號
的使用能夠處理這個情況
接收端必須指定確認的封包
序號
需要倒數計時器
rdt3.0 傳送端
sndpkt = make_pkt(0、 data、 checksum) udt_send(sndpkt)
start_timer rdt_send(data)
等待 ACK 訊息0
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt、1) )
等待從上 一層傳來 的呼叫1
sndpkt = make_pkt(1、 data、
checksum)
udt_send(sndpkt) start_timer
rdt_send(data)
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt、0)
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt、0) )
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt、1)
stop_timer stop_timer
udt_send(sndpkt) start_timer
timeout
udt_send(sndpkt) start_timer
timeout
rdt_rcv(rcvpkt)
等待從上 一層傳來 的呼叫0
等待 ACK 訊息1
Λ
rdt_rcv(rcvpkt)
Λ Λ
Λ
rdt3.0 的運作
rdt3.0 的運作
rdt3.0的效能
rdt3.0 能夠運作、 但是效能很糟
範例: 1 Gbps 的連結、 15 毫秒 終端對終端傳遞延遲
、 1KB 的封包:
Ttransmit = 8kb/pkt
10**9 b/sec = 8 毫秒
U sender: 使用率 – 傳送端將位元傳入通道的時間比例
U sender = .008
30.008 = 0.00027 L / R
RTT + L / R = L (封包長度位元)
R (傳送速率、 bps) =
每 30 毫秒 1KB 封包 -> 33kB/sec 生產量在 1 Gbps 連結上
網路協定限制了實體資源的使用!
rdt3.0: 停止並等待的機制
在 t = 0 時、傳送第1個封包的第1個位元
sender receiver
RTT
在t = L / R時、傳送第1個封包的最後1個位元
第一個封包的第一個位元到達
第一個封包的最後一個位元到達、並且送出 ACK
在t = RTT + L / R時、ACK到達、然 後送出下1個封包
U sender = .008
30.008 = 0.00027 L / R
RTT + L / R =
Pipelined protocols管線化協定
Pipelining: sender allows multiple, “in-flight”, yet-to-be- acknowledged pkts
管線化: 傳送端允許多個、 “飛行中的”、 還沒有被確認的封包
range of sequence numbers must be increased序號的範圍必須增加
buffering at sender and/or receiver傳送端 和/或 接收端需要暫存器
Two generic forms of pipelined protocols: go-Back-N, selective repeat
兩種管線化協定的一般性型態: 回送N、 選擇性重複
Pipelining: increased utilization 增加使用率
first packet bit transmitted, t = 0
sender receiver
RTT last bit transmitted, t = L / R
first packet bit arrives
last packet bit arrives, send ACK
ACK arrives, send next packet, t = RTT + L / R
last bit of 2nd packet arrives, send ACK last bit of 3rd packet arrives, send ACK
U sender = .024
30.008 = 0.0008 3 * L / R
RTT + L / R =
Increase utilization by a factor of 3!
管線化: 增加使用率
在 t = 0時、傳送第1個封包的第1個位元
傳送端 接收端
RTT
在 t = L/R時、傳送第1個封包的最後 一個位元
第1個封包的第1個位元到達
第1個封包的最後1個位元到達、送出ACK
ACK arrives、 send next packet、 t = RTT + L / R
第2個封包的最後1個位元到達、送出ACK 第3個封包的最後1個位元到達、送出ACK
U sender = .024
30.008 = 0.0008 3 * L / R
RTT + L / R =
增加3倍的使用率!
Go-Back-N 回送N
Sender:
k-bit seq # in pkt header 封包標頭的 k-位元序號
“window” of up to N, consecutive unack’ed pkts allowed
大小最多為N的“視窗” 、允許連續的未被確認的封包
ACK(n): ACKs all pkts up to, including seq # n - “cumulative ACK”
ACK(n): 確認小於或等於序號 n 的所有封包 - “累積 式確認”
May receive duplicate ACKs (see receiver) 可能會收到重複的確認 (見接收端)
Timer for each in-flight pkt 某個傳送中的封包都使用一個計時器
timeout(n): retransmit pkt n and all higher seq # pkts in window
重傳封包 n 以及在視窗中序號高於 n 的全部封包
GBN: sender extended FSM
Wait start_timer
udt_send(sndpkt[base]) udt_send(sndpkt[base+1])
…
udt_send(sndpkt[nextseqnum-1]) timeout
rdt_send(data)
if (nextseqnum < base+N) {
sndpkt[nextseqnum] = make_pkt(nextseqnum,data,chksum) udt_send(sndpkt[nextseqnum])
if (base == nextseqnum) start_timer
nextseqnum++
} else
refuse_data(data)
base = getacknum(rcvpkt)+1 If (base == nextseqnum)
stop_timer else
start_timer
rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt) base=1
nextseqnum=1
rdt_rcv(rcvpkt)
&& corrupt(rcvpkt)
Λ
GBN: receiver extended FSM
ACK-only: always send ACK for correctly- received pkt with highest in-order seq #
may generate duplicate ACKs
need only remember expectedseqnum
out-of-order pkt:
discard (don’t buffer) -> no receiver buffering!
Re-ACK pkt with highest in-order seq #
Wait
udt_send(sndpkt) default
rdt_rcv(rcvpkt)
&& notcurrupt(rcvpkt)
&& hasseqnum(rcvpkt,expectedseqnum) extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(expectedseqnum,ACK,chksum) udt_send(sndpkt)
expectedseqnum++
expectedseqnum=1 sndpkt =
make_pkt(expectedseqnum,ACK,chksum)
Λ
GBN: 接收端的擴充 FSM
只使用ACK: 只為接收順序正確的封包傳送 ACK
可能會產生重複的ACK
只需要記住 expectedseqnum
順序不正確的封包:
刪除 (不會暫存) -> 接收端沒有暫存器!
重新回應最高的順序正確封包
等待
udt_send(sndpkt) default
rdt_rcv(rcvpkt)
&& notcurrupt(rcvpkt)
&& hasseqnum(rcvpkt、
expectedseqnum) extract(rcvpkt、data) deliver_data(data)
sndpkt = make_pkt(expectedseqnum、ACK、
chksum)
udt_send(sndpkt) expectedseqnum++
expectedseqnum=1 sndpkt =
make_pkt(expectedseqnum、ACK、
chksum)
Λ
GBN in action
Selective Repeat選擇性重複
Receiver individually acknowledges all correctly received pkts
接收端分別確認所有正確接收的封包
Buffers pkts, as needed, for eventual in-order delivery to upper layer
依需要暫存封包、 最終會依序傳送到上一層
Sender only resends pkts for which ACK not received
傳送端只重傳沒有收到 ACK 的封包
Sender timer for each unACKed pkt
傳送端針對每一個未確認的封包需要一個計時器
Sender window傳送端視窗
N consecutive seq #’s N 個連續的序號
Again limits seq #s of sent, unACKed pkts
再次、用來限制傳送出去的、 未確認的封包序號
Selective repeat: sender, receiver windows
選擇性重複: 傳送端、 接收端視窗
Selective repeat
Data from above :
If next available seq # in window, send pkt
Timeout(n):
Resend pkt n, restart timer
ACK(n) in
[sendbase,sendbase+N]:
Mark pkt n as received
If n smallest unACKed pkt, advance window base to next unACKed seq #
sender
pkt n in [rcvbase,
rcvbase+N-1]
Send ACK(n)
Out-of-order: buffer
In-order: deliver (also deliver buffered, in-
order pkts), advance window to next not- yet-received pkt
pkt n in [rcvbase-
N,rcvbase-1]
ACK(n)
otherwise:
Ignore
receiver
選擇性重複
來自上層的資料 :
假如下一個可用的序號在視窗 內、則傳送封包
timeout(n):
重送封包 n、 重新啟動計時器
ACK(n) 在 [sendbase、
sendbase+N]中:
將封包 n 標示為已收到的
假如 n 為未確認的封包中最小 的、將視窗的 base 往前移到 下一個未回應的序號
傳送端
封包n 在 [rcvbase、
rcvbase+N-1]中
傳送 ACK(n)
不正確的順序: 暫存區
正確順序: 遞送 (也遞送暫 存區內順序錯誤的封包)、將 視窗前進到下一個未接收的 封包
封包 n 在 [rcvbase-N、
rcvbase-1]中
ACK(n) 否則:
忽略該封包
接收端
Selective repeat in action
Selective repeat: dilemma 選擇性重複: 困境
Example:
Seq #’s: 0, 1, 2, 3
Window size=3
Receiver sees no difference in two scenarios!接收端無法 分辨兩種情況的差別
Incorrectly passes duplicate data as new in (a)
不正確地重新傳送重複的 資料、如同 (a)
3.5 Connection-oriented
transport: TCP 連線導向傳輸
TCP: Overview
RFCs: 793, 1122, 1323, 2018, 2581 Point-to-point:點對點
One sender, one receiver一個傳送端、 一個接收端
Reliable, in-order byte steam:
可靠的、 有順序的位元組串流
No “message boundaries”沒有 “訊息界線”
Pipelined:管線化
TCP congestion and flow control set window size TCP壅塞控制和流量控制設定視窗大小
Send & receive buffers傳送端和接收端暫 存器
socket door
TCP send buffer
TCP receive buffer
socket door
segment application
writes data
application reads data
Full duplex data:全雙工資料傳輸
Bi-directional data flow in same connection 同一個連結中、雙向的資料流
MSS: maximum segment size最大資料分段大小
Connection-oriented:連線導向
Handshaking (exchange of control msgs) init’s sender, receiver state before data exchange
交握程序 (控制訊息的交換) 在資料開始交換之前、設 定傳送端和接收端的狀態
Flow controlled:流量控制
Sender will not overwhelm receiver 傳送端不會超過接收端
TCP segment structure
source port # dest port # 32 bits
application data
(variable length) sequence number
acknowledgement number Receive window
Urg data pnter checksum
F S P R A
head U
len not used
Options (variable length) URG: urgent data緊急資料
(generally not used) ACK: ACK #
valid PSH: push data now
馬上將資料送出 (generally not used)
RST, SYN, FIN:
connection estab連線建 立(setup設定, teardown 中斷, commands指令)
# bytes rcvr willing to accept 接收端願意
接收的位元組數 Counting by
bytes of data以 資料位元組計算 (not segments 非資料分段)
Internet checksum 網際網路檢查和 (as in UDP)
TCP seq. # ’s and ACKs
Seq. #’s:
byte stream
“number” of first byte in segment’s data
ACKs:
seq # of next byte expected from other side
cumulative ACK Q: how receiver
handles out-of- order segments
A: TCP spec doesn’t say, - up to
implementor
Host A Host B
Seq=42, A
CK=79, data = ‘C’
Seq=79, ACK=43, data = ‘C’
Seq=43, ACK=80
typesUser
‘C’
host ACKs receipt of echoed
‘C’
host ACKs receipt of
‘C’, echoes back ‘C’
simple telnet scenario time