-
version
3 (1 byte) -
ID
(8 bytes)2^64÷2^32÷3600÷24÷365÷100 = 1.361925195,既每秒产生2^32个ID,可以用一个世纪
-
packet ID
(8 bytes) -
CMD
: (1 byte)PSH
FIN
PING
ACK
数据为rwind
(64 bits) + n (可为 0 ) 个packet ID
RST
URG
SYN
// CMD 1 byte // PSH 0b1000,0000 // FIN 0b0100,0000 // PING 0b0010,0000 // ACK 0b0001,0000 // RST 0b0000,1000 // URG 0b0000,0100 // SYN 0b0000,0010 // RSV 0b0000,0000
-
length
(websocket like format 1~2 bytes)- 读 8 bits,如果为 255,则跳到第 2 步;其他就是
data
长度 - 读 16 bits,就是
data
的长度
- 读 8 bits,如果为 255,则跳到第 2 步;其他就是
-
data
(最多 65535 bytes)
9(2048) -> 11(100) -> 12(256) -> 14(1024) -> 16(1000)
require packet ID 10
readable 2048 bytes
10(400) -> 11(100) -> 12(256) -> 13(500) -> 14(1024) -> 15(8192) -> 16(1000)
buffer 中有 9(2048) acked
发送端发送了 10(400)
11(100)
底层问题,10没有收到
buffer 中有 9(2048) acked -> 11(100) not acked
检查是否有 ACK
等待发送,如果有就一并发送;否则尝试等待 10ms,并设置等待位为1,等待 ACK
为 11
如果在 10ms 内 12(256)
到达:
buffer 中有 9(2048) acked -> 11(100) not acked -> 12(256) not acked
发送 ack(rwind:262140-2048-100-256; IDs: 11 + 12)
buffer变成 9(2048) acked -> 11(100) acked -> 12(256) acked
如果在 10ms 内没收到新的数据包:
buffer 中有 9(2048) acked -> 11(100) not acked
发送 ack(rwind:262140-2048-100; IDs: 11)
buffer 变成 9(2048) acked -> 11(100) acked
在收到 URG
数据包时立即发送 ACK
wind
: 262140
RTT
: 0
- 计算公式: RTT = (n1+n2+n3+n4+...+n10)/n
- 当n = 10 时,重置n1 = last
RTT
,n = 1
buffer 中 10(400)not acked -> 11(100) not acked -> 12(256) not acked
如果 ack 了 11(100)
而已, wind
= 262140-2048-100
如果 ack 了 11(100)+12(256)
,wind
= 262140-2048-100-256
每发送一个包就以当时的 RTT
的 1.5 倍作为超时,超时重发,超过 x 次数则视为 link
异常
超时重发时带上 URG
flag
buffer 中 9(2048) acked -> 11(100) not acked
最多只能读取 2048 bytes
读完后,检查是否有 ACK
等待,如果有,一并发送;没有就设置等待位为1,等待 ACK
没有
如果buffer 中 9(2048) acked -> 10(400) not acked
最多能读取 2048+400 bytes
读完后,检查是否有 ACK
等待,如果有,一并发送;没有就设置等待位为1,等待 ACK
为10
发送 SYN
,等待接收 SYN_ACK
,超时时长为 RTT
。收到 SYN_ACK
后,发送 ACK
并通知最大 wind
调用 manager.Dial(host:port, b []byte)
将会获得一个 link
。如果 b
不为 nil
,则发送 SYN
时附带数据 b []byte
,当 b []byte
大于65535 bytes,时,会自动发送下一个packet
-
func CloseWrite()
发送FIN
,并等待FIN_ACK
,超时时长为RTT
的 1.5 倍。若超时则发送RST
并且直接关闭link
。在write
被 close 之前,read
也被 close 了的话,就可以 close 掉整个link
。 -
func CloseRead()
不发送任何东西,仅不允许再读任何数据。如果write
已经 close , 则关闭整个link
-
func Close()
当read
已经 close 时,如果write
已经被 close,则直接关闭link
;如果没有则按照func CloseWrite()
做法。如果read
没有 close,则直接发送RST
然后关闭link
一个 base
应该对应一个 io.ReadWriteCloser
,base
应该只负责传输数据和维护自己的状态 。base
维护一个发送队列。base
由 manager
决定是否开启 PING
维护一个 map[linkID]link
-
func New(generators []BaseGenerator)
让manager
同时使用多个BaseGenerator
,既允许manager
中管理的baser
是不同种类的流,所accept
到的io.ReadWriteCloser
全都会成为base
纳入manager
的管理 -
func AddBaseGenerator(generators []BaseGenerator)
让manager
增加BaseGenerator
-
func Close()
关闭这个manager
,同时会关闭这个manager
所管理的base
和link
-
func IsClosed()
返回这个manager
是否已关闭
type BaseGenerator interface {
Dial() (io.ReadWriteCloser, error)
Accept() (io.ReadWriteCloser, error)
}