Bagaimana untuk membaca kandungan buffered sepenuhnya dari soket tcp selepas menutup sambungan klien?

PHPz
Lepaskan: 2024-02-11 16:33:18
ke hadapan
452 orang telah melayarinya

关闭客户端连接后如何从 tcp 套接字完全读取缓冲内容?

Dalam pengaturcaraan rangkaian, cara membaca sepenuhnya kandungan buffer dari soket tcp selepas menutup sambungan klien adalah masalah biasa. Apabila pelanggan menutup sambungan, mungkin masih terdapat data yang belum dibaca pada bahagian pelayan. Untuk memastikan kandungan penimbal dibaca sepenuhnya, kaedah berikut boleh digunakan: 1. Gunakan bacaan gelung sehingga bendera tamat data dibaca 2. Tetapkan tamat masa dan lompat keluar daripada gelung jika data tidak dibaca dalam masa yang ditetapkan; 3. Gunakan soket tidak menyekat dan semak sama ada terdapat data untuk dibaca melalui pengundian. Kaedah di atas boleh memastikan kandungan penimbal dibaca sepenuhnya dari soket tcp, meningkatkan kestabilan dan kebolehpercayaan komunikasi rangkaian.

Kandungan soalan

Saya mempunyai pelayan go yang mendengar pada soket tcp, dan semasa penutupan saya mahu ia memberitahu pelanggan untuk berhenti menghantar lebih banyak data, tetapi juga membaca semua yang telah dihantar oleh pelanggan setakat ini. Apa yang saya lihat ialah apabila sambungan pelanggan ditutup, pelayan berhenti membaca, tetapi ia tidak pernah menerima semua yang pelanggan fikir ia dihantar. Apa yang saya fikir sedang berlaku ialah OS menimbal paket tcp yang diterima dan kemudian membuangnya apabila pelayan menutup sambungan klien.

Berikut adalah program yang menunjukkan masalah. Pelayan mendengar dan mencetak apa yang diterima oleh pelanggan dan mencetak apa yang dihantarnya. Pelayan mengganggu pelanggan untuk menghentikannya, tetapi pada akhirnya saya mahu kedua-dua senarai itu sama.

  • Contoh ini menggunakan bufio.scanner untuk membaca soket, tetapi saya juga telah mencuba hanya membaca bait daripada sambungan tetapi mendapat hasil yang sama.

  • conn.(*net.tcpconn).closewrite() Bunyi seperti yang saya mahukan, tetapi ini nampaknya tidak mematahkan pelanggan sama sekali.

  • conn.(*net.tcpconn).setreadbuffer(0) - Mencuba ini juga, tetapi 0 bukan nilai yang dibenarkan (panik).

package main

import (
    "bufio"
    "fmt"
    "net"
    "strconv"
    "sync"
    "time"
)

const port = ":8888"

var wg sync.waitgroup

func main() {
    wg.add(1)
    go func() {
        // wait for the server to start
        time.sleep(1000 * time.millisecond)
        client()
    }()

    // server listens
    wg.add(1)
    server()

    wg.wait()
}

func server() {
    defer wg.done()

    listener, err := net.listen("tcp", port)
    if err != nil {
        panic(err)
    }

    received := make([]string, 0)
    conn, err := listener.accept()
    if err != nil {
        panic(err)
    }

    defer conn.close()

    scanner := bufio.newscanner(conn)

    for i := 0; scanner.scan(); i++ {
        received = append(received, scanner.text())

        // arbitrary condition: simulate a server shutdown - interrupt the client
        if len(received) == 2 {
            _ = conn.(*net.tcpconn).close()
        }
    }

    fmt.println("server received: ", received)
}

func client() {
    defer wg.done()

    conn, err := net.dial("tcp", port)
    if err != nil {
        panic(err)
    }

    sent := make([]string, 0)
    defer conn.close()

    for i := 0; i < 50000; i++ {
        v := strconv.itoa(i)
        _, err := conn.write([]byte(v + "\n"))
        if err != nil {
            fmt.println("client interrupted:", err)
            break
        } else {
            sent = append(sent, v)
            // slow down the sends to make output readable
            //time.sleep(1 * time.millisecond)
        }
    }
    fmt.println("client sent: ", sent)
}
Salin selepas log masuk

Keluaran pada mesin saya adalah seperti ini:

Server received:  [0 1 2]
Client interrupted: write tcp 127.0.0.1:49274->127.0.0.1:8888: write: broken pipe
Client sent:  [0 1 2 3 4 5 6 7 8 9 10 11 12 13]
Salin selepas log masuk

Penyelesaian

TCP hanya menyediakan aliran bait dua arah yang boleh dipercayai tanpa sebarang semantik yang wujud. Jika pelayan mahu pelanggan memberi isyarat bahawa ia tidak sepatutnya menghantar data lagi, ia mesti melaksanakan fungsi ini sebagai sebahagian daripada protokol aplikasi, lapisan di atas pengangkutan data tulen yang disediakan oleh TCP.

Atas ialah kandungan terperinci Bagaimana untuk membaca kandungan buffered sepenuhnya dari soket tcp selepas menutup sambungan klien?. 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
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!