io.Salin tamat masa apabila keepalive dilumpuhkan

PHPz
Lepaskan: 2024-02-13 21:36:08
ke hadapan
1210 orang telah melayarinya

禁用 keepalive 时 io.Copy 超时

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!

Kandungan soalan

Apabila saya melumpuhkan linux keepalive

sudo sysctl -w net.ipv4.tcp_keepalive_probes=0
Salin selepas log masuk

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()

}

Salin selepas log masuk

io.Copy akan mengembalikan "splice: sambungan tamat masa"

Jika saya mendayakan keepalive

sudo sysctl -w net.ipv4.tcp_keepalive_probes=3
Salin selepas log masuk

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()
Salin selepas log masuk

Baca tamat masa selepas 15 saat, tidak berfungsi selama 30 saat

Mengapa ini berlaku?

Penyelesaian

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!

Label berkaitan:
sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan