当我禁用Linux keepalive时,
sudo sysctl -w net.ipv4.tcp_keepalive_probes=0
字符串
并运行以下代码
package main
import (
"fmt"
"io"
"net"
"os"
"sync"
"time"
)
func main() {
go func() {
listen, err := net.Listen("tcp", "127.0.0.1:9390")
if err != nil {
fmt.Printf("net listen fail, reason: [%s]\n", err.Error())
os.Exit(1)
}
defer listen.Close()
for {
conn, err := listen.Accept()
if err != nil {
fmt.Printf("net accept fail, reason: [%s]\n", err.Error())
continue
}
_, err = io.Copy(conn, conn)
if err != nil {
fmt.Printf("net Copy fail, reason: [%s]\n", err.Error())
continue
}
conn.Close()
}
}()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for {
time.Sleep(1 * time.Second)
tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9390")
fmt.Println("tcp client resolve success: ", tcpAddr.String())
tcpConn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
fmt.Println("tcp connect fail: ", err.Error())
return
}
time.Sleep(100 * time.Second)
tcpConn.Close()
fmt.Println("tcp end")
}
}()
wg.Wait()
}
型
io.复制将返回“拼接:连接超时”
如果启用keepalive,
sudo sysctl -w net.ipv4.tcp_keepalive_probes=3
型
io.复制就可以了
我尝试tcp客户端以1秒的间隔发送数据包,并禁用tcp_keepalive,它也可以。
我写另一段代码来代替io,收到
buf := make([]byte, 10)
for {
conn.SetReadDeadline(time.Now().Add(30 * time.Second))
n, err := conn.Read(buf)
if err != nil {
fmt.Println("read fail: ", err.Error())
break
}
_, err = conn.Write(buf[:n])
if err != nil {
fmt.Println("write fail: ", err.Error())
break
}
}
conn.Close()
型
15秒后读超时,30秒后不工作
为什么会这样,太奇怪了吧?
1条答案
按热度按时间ojsjcaue1#
主持人:当“内核tcp堆栈”使用keepalive检测网络时,当“内核tcp堆栈”需要发送keepalive时,net.ipv4.tcp_keepalive_probes = 0将超时