-
version3 (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)PSHFINPINGACK数据为rwind(64 bits) + n (可为 0 ) 个packet IDRSTURGSYN
// 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)
}