Mengapakah `socket.recv()` Terhenti Apabila Pelayan Tidak Menghantar Data Kembali?

Patricia Arquette
Lepaskan: 2024-11-22 22:33:26
asal
865 orang telah melayarinya

Why Does `socket.recv()` Stall When the Server Doesn't Send Data Back?

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

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

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

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

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!

sumber:php.cn
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
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan