Rumah > Artikel > pembangunan bahagian belakang > Bagaimana untuk membaca kandungan buffered sepenuhnya dari soket tcp selepas menutup sambungan klien?
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.
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) }
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]
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!