Memahami Gelagat Soket: Mengapa Socket.recv() Berhenti Tanpa Data Dihantar
Soket Python, seperti sambungan TCP, berkelakuan sebagai aliran data yang mengalir antara pelanggan dan pelayan. Artikel ini menyelidiki sebab di sebalik isu di mana panggilan socket.recv() gagal mengembalikan data selepas penghantaran data diubah suai.
Contoh Pelayan Gema
Pertimbangkan contoh pelayan gema Python daripada dokumentasi rasmi. Pelayan ini mendengar sambungan masuk, menerima data dan menggemakannya kembali kepada pelanggan. Coretan kod berikut mereplikasi kelakuan pelayan asal:
import socket HOST = '' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(data) conn.close()
Mengubah Gelagat Pelayan
Isu timbul apabila kod diubah suai untuk tidak menghantar data kembali kepada klien :
while True: data = conn.recv(1024) if not data: break conn.close()
Dalam kod yang diubah suai ini, gelung sementara menerima data daripada klien tanpa henti, tetapi pelayan tidak pernah menghantar data kembali. Ini menyebabkan pelanggan terhenti selama-lamanya pada panggilan socket.recv().
Memahami Aliran Komunikasi
Soket TCP tidak mengekalkan perhubungan satu dengan satu antara menghantar dan menerima panggilan pada titik akhir yang berbeza. Sebaliknya, protokol mentakrifkan peraturan untuk komunikasi. Dalam kes ini, pelayan gema asal melaksanakan peraturan di mana pelayan akan menggemakan semula data yang diterima sehingga klien menutup sambungan.
Apabila gelagat pelayan ditukar, peraturan telah diubah suai dengan berkesan. Pelayan kini hanya menerima data dan membuangnya sehingga klien menutup sambungan. Pelayan tidak pernah menghantar data kembali kepada klien.
Menyesuaikan Gelagat Pelanggan
Untuk bekerja dengan pelayan yang diubah suai, pelanggan mesti melaraskan tingkah lakunya. Memandangkan pelayan tidak lagi menghantar data secara aktif, pelanggan menganggap bahawa menerima semula data menunjukkan sambungan yang lengkap. Untuk memudahkan ini, pelanggan harus menutup bahagian keluar sambungannya untuk memberi isyarat kepada pelayan bahawa ia telah selesai menghantar data. Pelanggan kemudiannya boleh melakukan berbilang panggilan recv untuk mengendalikan sebarang kemungkinan pemecahan data masuk.
Kod Kemas Kini
Di bawah adalah kod yang dikemas kini untuk pelayan dan pelanggan yang mematuhi peraturan yang diubah suai komunikasi:
Pelayan:
import socket HOST = '' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(b'ok') conn.shutdown(socket.SHUT_WR) conn.close()
Pelanggan:
import socket HOST = 'localhost' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall(b'Hello, world') s.shutdown(socket.SHUT_WR) data = b'' while True: buf = s.recv(1024) if not buf: break data += buf s.close() print('Received', repr(data))
Dengan memahami sifat berasaskan aliran Soket TCP dan melaraskan peraturan komunikasi dengan sewajarnya, adalah mungkin untuk menyelesaikan isu di mana socket.recv() terhenti tanpa data dihantar.
Atas ialah kandungan terperinci Mengapakah `socket.recv()` Terhenti Apabila Pelayan Tidak Menghantar Data Kembali?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!