mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-24 13:13:06 +08:00
keepalive 成功解决 ZWP 问题 当接收端不理发送端的时候 每 idleTime 就会重发一个询问报文
This commit is contained in:
@@ -97,6 +97,16 @@ func (conn *TcpConn) Close() {
|
|||||||
conn.ep.Close()
|
conn.ep.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSockOpt 设置socket属性 暂时只测试keepalive
|
||||||
|
func (conn *TcpConn) SetSockOpt(opt interface{}) error {
|
||||||
|
err := conn.ep.SetSockOpt(opt)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s", err.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Listener tcp连接监听器
|
// Listener tcp连接监听器
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
raddr tcpip.FullAddress
|
raddr tcpip.FullAddress
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ func main() {
|
|||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
log.Println("服务端 建立连接")
|
log.Println("服务端 建立连接")
|
||||||
_ = conn
|
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
for {
|
for {
|
||||||
@@ -171,12 +171,22 @@ func main() {
|
|||||||
}
|
}
|
||||||
log.Printf("客户端 建立连接\n")
|
log.Printf("客户端 建立连接\n")
|
||||||
|
|
||||||
|
conn.SetSockOpt(tcpip.KeepaliveEnabledOption(1))
|
||||||
|
conn.SetSockOpt(tcpip.KeepaliveIntervalOption(75 * time.Second))
|
||||||
|
conn.SetSockOpt(tcpip.KeepaliveIdleOption(30 * time.Second)) // 30s的探活心跳
|
||||||
|
conn.SetSockOpt(tcpip.KeepaliveCountOption(9))
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
log.Printf("\n\n客户端 写入数据")
|
log.Printf("\n\n客户端 写入数据")
|
||||||
buf := make([]byte, 1<<20)
|
buf := make([]byte, 1<<20)
|
||||||
conn.Write(buf)
|
conn.Write(buf)
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
buf = make([]byte, 1<<22)
|
||||||
conn.Write(buf)
|
conn.Write(buf)
|
||||||
|
|
||||||
time.Sleep(500 * time.Minute)
|
time.Sleep(500 * time.Minute)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
@@ -383,6 +384,32 @@ type ReceiveQueueSizeOption int
|
|||||||
// SO_TIMESTAMP socket control messages are enabled.
|
// SO_TIMESTAMP socket control messages are enabled.
|
||||||
type TimestampOption int
|
type TimestampOption int
|
||||||
|
|
||||||
|
// TCPInfoOption is used by GetSockOpt to expose TCP statistics.
|
||||||
|
//
|
||||||
|
// TODO: Add and populate stat fields.
|
||||||
|
type TCPInfoOption struct {
|
||||||
|
RTT time.Duration
|
||||||
|
RTTVar time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeepaliveEnabledOption is used by SetSockOpt/GetSockOpt to specify whether
|
||||||
|
// TCP keepalive is enabled for this socket.
|
||||||
|
type KeepaliveEnabledOption int
|
||||||
|
|
||||||
|
// KeepaliveIdleOption is used by SetSockOpt/GetSockOpt to specify the time a
|
||||||
|
// connection must remain idle before the first TCP keepalive packet is sent.
|
||||||
|
// Once this time is reached, KeepaliveIntervalOption is used instead.
|
||||||
|
type KeepaliveIdleOption time.Duration
|
||||||
|
|
||||||
|
// KeepaliveIntervalOption is used by SetSockOpt/GetSockOpt to specify the
|
||||||
|
// interval between sending TCP keepalive packets.
|
||||||
|
type KeepaliveIntervalOption time.Duration
|
||||||
|
|
||||||
|
// KeepaliveCountOption is used by SetSockOpt/GetSockOpt to specify the number
|
||||||
|
// of un-ACKed TCP keepalives that will be sent before the connection is
|
||||||
|
// closed.
|
||||||
|
type KeepaliveCountOption int
|
||||||
|
|
||||||
// MulticastTTLOption is used by SetSockOpt/GetSockOpt to control the default
|
// MulticastTTLOption is used by SetSockOpt/GetSockOpt to control the default
|
||||||
// TTL value for multicast messages. The default is 1.
|
// TTL value for multicast messages. The default is 1.
|
||||||
type MulticastTTLOption uint8
|
type MulticastTTLOption uint8
|
||||||
|
|||||||
@@ -247,7 +247,6 @@ func (h *handshake) synSentState(s *segment) *tcpip.Error {
|
|||||||
h.flags |= flagAck
|
h.flags |= flagAck
|
||||||
h.mss = rcvSynOpts.MSS
|
h.mss = rcvSynOpts.MSS
|
||||||
h.sndWndScale = rcvSynOpts.WS
|
h.sndWndScale = rcvSynOpts.WS
|
||||||
logger.NOTICE(atoi(h.sndWnd), atoi(h.sndWndScale), atoi(h.rcvWnd))
|
|
||||||
|
|
||||||
// If this is a SYN ACK response, we only need to acknowledge the SYN
|
// If this is a SYN ACK response, we only need to acknowledge the SYN
|
||||||
// and the handshake is completed.
|
// and the handshake is completed.
|
||||||
@@ -351,8 +350,6 @@ func (h *handshake) handleSegment(s *segment) *tcpip.Error {
|
|||||||
if !s.flagIsSet(flagSyn) && h.sndWndScale > 0 {
|
if !s.flagIsSet(flagSyn) && h.sndWndScale > 0 {
|
||||||
h.sndWnd <<= uint8(h.sndWndScale) // 收紧发送窗口
|
h.sndWnd <<= uint8(h.sndWndScale) // 收紧发送窗口
|
||||||
logger.NOTICE("扩张发送窗口到", atoi(h.sndWnd))
|
logger.NOTICE("扩张发送窗口到", atoi(h.sndWnd))
|
||||||
} else {
|
|
||||||
logger.NOTICE("原有发送窗口与服务端的接收窗口大小相同", atoi(h.sndWnd))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch h.state {
|
switch h.state {
|
||||||
@@ -778,19 +775,12 @@ func (e *endpoint) handleSegments() *tcpip.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *endpoint) keepaliveTimerExpired() *tcpip.Error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE 这里是 Nagle algorithm 的实现 也就是用来解决 发送端的 ZWP 问题
|
// NOTE 这里是 Nagle algorithm 的实现 也就是用来解决 发送端的 ZWP 问题
|
||||||
func (e *endpoint) resetKeepaliveTimer(receivedData bool) *tcpip.Error {
|
func (e *endpoint) keepaliveTimerExpired() *tcpip.Error {
|
||||||
e.keepalive.Lock()
|
e.keepalive.Lock()
|
||||||
defer e.keepalive.Unlock()
|
if !e.keepalive.enabled || !e.keepalive.timer.checkExpiration() {
|
||||||
if receivedData {
|
e.keepalive.Unlock()
|
||||||
e.keepalive.unacked = 0
|
return nil
|
||||||
logger.NOTICE("测试 keepalive 有数据进入")
|
|
||||||
} else {
|
|
||||||
logger.NOTICE("测试 keepalive 无数据进入")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.keepalive.unacked >= e.keepalive.count {
|
if e.keepalive.unacked >= e.keepalive.count {
|
||||||
@@ -807,6 +797,28 @@ func (e *endpoint) resetKeepaliveTimer(receivedData bool) *tcpip.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 充值 keepalive 的时间
|
||||||
|
func (e *endpoint) resetKeepaliveTimer(receivedData bool) {
|
||||||
|
e.keepalive.Lock()
|
||||||
|
defer e.keepalive.Unlock()
|
||||||
|
if receivedData {
|
||||||
|
e.keepalive.unacked = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the keepalive timer IFF it's enabled and there is no pending
|
||||||
|
// data to send.
|
||||||
|
if !e.keepalive.enabled || e.snd == nil || e.snd.sndUna != e.snd.sndNxt {
|
||||||
|
e.keepalive.timer.disable()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.keepalive.unacked > 0 {
|
||||||
|
e.keepalive.timer.enable(e.keepalive.interval)
|
||||||
|
} else {
|
||||||
|
e.keepalive.timer.enable(e.keepalive.idle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// disableKeepaliveTimer stops the keepalive timer.
|
// disableKeepaliveTimer stops the keepalive timer.
|
||||||
func (e *endpoint) disableKeepaliveTimer() {
|
func (e *endpoint) disableKeepaliveTimer() {
|
||||||
e.keepalive.Lock()
|
e.keepalive.Lock()
|
||||||
@@ -937,6 +949,7 @@ func (e *endpoint) protocolMainLoop(handshake bool) *tcpip.Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if n¬ifyKeepaliveChanged != 0 {
|
if n¬ifyKeepaliveChanged != 0 {
|
||||||
|
e.resetKeepaliveTimer(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -59,12 +59,15 @@ type SACKInfo struct {
|
|||||||
|
|
||||||
// keepalive is a synchronization wrapper used to appease stateify. See the
|
// keepalive is a synchronization wrapper used to appease stateify. See the
|
||||||
// comment in endpoint, where it is used.
|
// comment in endpoint, where it is used.
|
||||||
//
|
// KeepAlive默认情况下是关闭的,可以被上层应用开启和关闭
|
||||||
|
// tcp_keepalive_probes: 在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包次数,默认值为9(次)
|
||||||
// +stateify savable
|
// +stateify savable
|
||||||
type keepalive struct {
|
type keepalive struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
enabled bool
|
enabled bool
|
||||||
|
// KeepAlive的空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2小时)
|
||||||
idle time.Duration
|
idle time.Duration
|
||||||
|
// KeepAlive探测包的发送间隔,默认值为75s
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
count int
|
count int
|
||||||
unacked int
|
unacked int
|
||||||
@@ -842,12 +845,241 @@ func (e *endpoint) zeroReceiveWindow(scale uint8) bool {
|
|||||||
return ((e.rcvBufSize - e.rcvBufUsed) >> scale) == 0 // 接收方接收空间告急
|
return ((e.rcvBufSize - e.rcvBufUsed) >> scale) == 0 // 接收方接收空间告急
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSockOpt sets a socket option
|
||||||
func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
|
||||||
|
switch v := opt.(type) {
|
||||||
|
case tcpip.KeepaliveEnabledOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
e.keepalive.enabled = v != 0
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
e.notifyProtocolGoroutine(notifyKeepaliveChanged)
|
||||||
|
|
||||||
|
case tcpip.KeepaliveIdleOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
e.keepalive.idle = time.Duration(v)
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
e.notifyProtocolGoroutine(notifyKeepaliveChanged)
|
||||||
|
|
||||||
|
case tcpip.KeepaliveIntervalOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
e.keepalive.interval = time.Duration(v)
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
e.notifyProtocolGoroutine(notifyKeepaliveChanged)
|
||||||
|
|
||||||
|
case tcpip.KeepaliveCountOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
e.keepalive.count = int(v)
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
e.notifyProtocolGoroutine(notifyKeepaliveChanged)
|
||||||
|
|
||||||
|
//case tcpip.NoDelayOption:
|
||||||
|
// e.mu.Lock()
|
||||||
|
// e.noDelay = v != 0
|
||||||
|
// e.mu.Unlock()
|
||||||
|
// return nil
|
||||||
|
|
||||||
|
//case tcpip.ReuseAddressOption:
|
||||||
|
// e.mu.Lock()
|
||||||
|
// e.reuseAddr = v != 0
|
||||||
|
// e.mu.Unlock()
|
||||||
|
// return nil
|
||||||
|
|
||||||
|
//case tcpip.ReceiveBufferSizeOption:
|
||||||
|
// // Make sure the receive buffer size is within the min and max
|
||||||
|
// // allowed.
|
||||||
|
// var rs ReceiveBufferSizeOption
|
||||||
|
// size := int(v)
|
||||||
|
// if err := e.stack.TransportProtocolOption(ProtocolNumber, &rs); err == nil {
|
||||||
|
// if size < rs.Min {
|
||||||
|
// size = rs.Min
|
||||||
|
// }
|
||||||
|
// if size > rs.Max {
|
||||||
|
// size = rs.Max
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mask := uint32(notifyReceiveWindowChanged)
|
||||||
|
|
||||||
|
// e.rcvListMu.Lock()
|
||||||
|
|
||||||
|
// // Make sure the receive buffer size allows us to send a
|
||||||
|
// // non-zero window size.
|
||||||
|
// scale := uint8(0)
|
||||||
|
// if e.rcv != nil {
|
||||||
|
// scale = e.rcv.rcvWndScale
|
||||||
|
// }
|
||||||
|
// if size>>scale == 0 {
|
||||||
|
// size = 1 << scale
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Make sure 2*size doesn't overflow.
|
||||||
|
// if size > math.MaxInt32/2 {
|
||||||
|
// size = math.MaxInt32 / 2
|
||||||
|
// }
|
||||||
|
|
||||||
|
// wasZero := e.zeroReceiveWindow(scale)
|
||||||
|
// e.rcvBufSize = size
|
||||||
|
// if wasZero && !e.zeroReceiveWindow(scale) {
|
||||||
|
// mask |= notifyNonZeroReceiveWindow
|
||||||
|
// }
|
||||||
|
// e.rcvListMu.Unlock()
|
||||||
|
|
||||||
|
// e.segmentQueue.setLimit(2 * size)
|
||||||
|
|
||||||
|
// e.notifyProtocolGoroutine(mask)
|
||||||
|
// return nil
|
||||||
|
|
||||||
|
//case tcpip.SendBufferSizeOption:
|
||||||
|
// // Make sure the send buffer size is within the min and max
|
||||||
|
// // allowed.
|
||||||
|
// size := int(v)
|
||||||
|
// var ss SendBufferSizeOption
|
||||||
|
// if err := e.stack.TransportProtocolOption(ProtocolNumber, &ss); err == nil {
|
||||||
|
// if size < ss.Min {
|
||||||
|
// size = ss.Min
|
||||||
|
// }
|
||||||
|
// if size > ss.Max {
|
||||||
|
// size = ss.Max
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// e.sndBufMu.Lock()
|
||||||
|
// e.sndBufSize = size
|
||||||
|
// e.sndBufMu.Unlock()
|
||||||
|
|
||||||
|
// return nil
|
||||||
|
|
||||||
|
//case tcpip.V6OnlyOption:
|
||||||
|
// // We only recognize this option on v6 endpoints.
|
||||||
|
// if e.netProto != header.IPv6ProtocolNumber {
|
||||||
|
// return tcpip.ErrInvalidEndpointState
|
||||||
|
// }
|
||||||
|
|
||||||
|
// e.mu.Lock()
|
||||||
|
// defer e.mu.Unlock()
|
||||||
|
|
||||||
|
// // We only allow this to be set when we're in the initial state.
|
||||||
|
// if e.state != stateInitial {
|
||||||
|
// return tcpip.ErrInvalidEndpointState
|
||||||
|
// }
|
||||||
|
|
||||||
|
// e.v6only = v != 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||||
|
switch o := opt.(type) {
|
||||||
|
case tcpip.ErrorOption:
|
||||||
|
e.lastErrorMu.Lock()
|
||||||
|
err := e.lastError
|
||||||
|
e.lastError = nil
|
||||||
|
e.lastErrorMu.Unlock()
|
||||||
|
return err
|
||||||
|
|
||||||
|
case *tcpip.SendBufferSizeOption:
|
||||||
|
e.sndBufMu.Lock()
|
||||||
|
*o = tcpip.SendBufferSizeOption(e.sndBufSize)
|
||||||
|
e.sndBufMu.Unlock()
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
case *tcpip.ReceiveBufferSizeOption:
|
||||||
|
e.rcvListMu.Lock()
|
||||||
|
*o = tcpip.ReceiveBufferSizeOption(e.rcvBufSize)
|
||||||
|
e.rcvListMu.Unlock()
|
||||||
|
return nil
|
||||||
|
|
||||||
|
//case *tcpip.ReceiveQueueSizeOption:
|
||||||
|
// v, err := e.readyReceiveSize()
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// *o = tcpip.ReceiveQueueSizeOption(v)
|
||||||
|
// return nil
|
||||||
|
|
||||||
|
//case *tcpip.NoDelayOption:
|
||||||
|
// e.mu.RLock()
|
||||||
|
// v := e.noDelay
|
||||||
|
// e.mu.RUnlock()
|
||||||
|
|
||||||
|
// *o = 0
|
||||||
|
// if v {
|
||||||
|
// *o = 1
|
||||||
|
// }
|
||||||
|
// return nil
|
||||||
|
|
||||||
|
//case *tcpip.ReuseAddressOption:
|
||||||
|
// e.mu.RLock()
|
||||||
|
// v := e.reuseAddr
|
||||||
|
// e.mu.RUnlock()
|
||||||
|
|
||||||
|
// *o = 0
|
||||||
|
// if v {
|
||||||
|
// *o = 1
|
||||||
|
// }
|
||||||
|
// return nil
|
||||||
|
|
||||||
|
case *tcpip.V6OnlyOption:
|
||||||
|
// We only recognize this option on v6 endpoints.
|
||||||
|
if e.netProto != header.IPv6ProtocolNumber {
|
||||||
|
return tcpip.ErrUnknownProtocolOption
|
||||||
|
}
|
||||||
|
|
||||||
|
e.mu.Lock()
|
||||||
|
v := e.v6only
|
||||||
|
e.mu.Unlock()
|
||||||
|
|
||||||
|
*o = 0
|
||||||
|
if v {
|
||||||
|
*o = 1
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case *tcpip.TCPInfoOption:
|
||||||
|
*o = tcpip.TCPInfoOption{}
|
||||||
|
e.mu.RLock()
|
||||||
|
snd := e.snd
|
||||||
|
e.mu.RUnlock()
|
||||||
|
if snd != nil {
|
||||||
|
snd.rtt.Lock()
|
||||||
|
o.RTT = snd.rtt.srtt
|
||||||
|
o.RTTVar = snd.rtt.rttvar
|
||||||
|
snd.rtt.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case *tcpip.KeepaliveEnabledOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
v := e.keepalive.enabled
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
|
||||||
|
*o = 0
|
||||||
|
if v {
|
||||||
|
*o = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
case *tcpip.KeepaliveIdleOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
*o = tcpip.KeepaliveIdleOption(e.keepalive.idle)
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
|
||||||
|
case *tcpip.KeepaliveIntervalOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
*o = tcpip.KeepaliveIntervalOption(e.keepalive.interval)
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
|
||||||
|
case *tcpip.KeepaliveCountOption:
|
||||||
|
e.keepalive.Lock()
|
||||||
|
*o = tcpip.KeepaliveCountOption(e.keepalive.count)
|
||||||
|
e.keepalive.Unlock()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcpip.ErrUnknownProtocolOption
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, vv buffer.VectorisedView) {
|
func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, vv buffer.VectorisedView) {
|
||||||
|
|||||||
@@ -70,10 +70,7 @@ func (r *receiver) nonZeroWindow() {
|
|||||||
// don't need to immediately announce a nonzero one.
|
// don't need to immediately announce a nonzero one.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.NOTICE("探测到 0 窗口")
|
r.ep.snd.sendAck()
|
||||||
// FIXME 揭开注释
|
|
||||||
//time.Sleep(100 * time.Second)
|
|
||||||
//r.ep.snd.sendAck()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *receiver) consumeSegment(s *segment, segSeq seqnum.Value, segLen seqnum.Size) bool {
|
func (r *receiver) consumeSegment(s *segment, segSeq seqnum.Value, segLen seqnum.Size) bool {
|
||||||
|
|||||||
@@ -263,9 +263,6 @@ func (s *sender) updateMaxPayloadSize(mtu, count int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *sender) sendAck() {
|
func (s *sender) sendAck() {
|
||||||
if s.ep.id.LocalPort == 9999 {
|
|
||||||
logger.NOTICE("之前的数据已经确认过了 服务端更新自己的确认边界", atoi(s.ep.rcv.rcvNxt))
|
|
||||||
}
|
|
||||||
s.sendSegment(buffer.VectorisedView{}, flagAck, s.sndNxt) // seq = cookies+1 ack ack|fin.seq+1
|
s.sendSegment(buffer.VectorisedView{}, flagAck, s.sndNxt) // seq = cookies+1 ack ack|fin.seq+1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,13 +344,12 @@ func (s *sender) sendSegment(data buffer.VectorisedView, flags byte, seq seqnum.
|
|||||||
rcvNxt, rcvWnd := s.ep.rcv.getSendParams()
|
rcvNxt, rcvWnd := s.ep.rcv.getSendParams()
|
||||||
|
|
||||||
// Remember the max sent ack.
|
// Remember the max sent ack.
|
||||||
old := s.maxSentAck
|
|
||||||
s.maxSentAck = rcvNxt
|
s.maxSentAck = rcvNxt
|
||||||
|
|
||||||
if s.ep.id.LocalPort == 9999 {
|
if s.ep.id.LocalPort == 9999 {
|
||||||
fmt.Println()
|
//fmt.Println()
|
||||||
log.Println("服务端要求客户端扩展窗口到", rcvWnd, "更新发送端的边缘", old, " TO ", s.maxSentAck)
|
//log.Println("服务端要求客户端扩展窗口到", rcvWnd, "更新发送端的边缘", old, " TO ", s.maxSentAck)
|
||||||
fmt.Println()
|
//fmt.Println()
|
||||||
}
|
}
|
||||||
return s.ep.sendRaw(data, flags, seq, rcvNxt, rcvWnd)
|
return s.ep.sendRaw(data, flags, seq, rcvNxt, rcvWnd)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user