editor php Yuzai hari ini akan memperkenalkan kepada anda masalah tentang "io.Copy timeout when keepalive is disabled". Apabila menggunakan fungsi io.Copy dalam bahasa Go untuk penghantaran data, jika keepalive dilumpuhkan, tamat masa penghantaran mungkin berlaku. Masalah ini mungkin menyebabkan beberapa masalah kepada pembangun, jadi kita perlu mengetahui beberapa penyelesaian untuk mengelakkan masalah ini daripada berlaku. Mari kita lihat bagaimana untuk menyelesaikan masalah ini!
Apabila saya melumpuhkan linux keepalive
sudo sysctl -w net.ipv4.tcp_keepalive_probes=0
Dan jalankan kod berikut
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.Copy akan mengembalikan "splice: sambungan tamat masa"
Jika saya mendayakan keepalive
sudo sysctl -w net.ipv4.tcp_keepalive_probes=3
io.Copy sudah memadai
Saya mencuba klien tcp untuk menghantar paket pada selang 1 saat dan melumpuhkan tcp_keepalive, itu juga berkesan.
Saya menulis kod lain untuk menggantikan io.Copy
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()
Baca tamat masa selepas 15 saat, tidak berfungsi selama 30 saat
Mengapa ini berlaku?
Jawapan: Apabila "kernel tcp stack" menggunakan keepalive untuk mengesan rangkaian, apabila "kernel tcp stack" perlu menghantar keepalive, net.ipv4.tcp_keepalive_probes = 0 akan tamat masa
Atas ialah kandungan terperinci io.Salin tamat masa apabila keepalive dilumpuhkan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!