Saya perlu mengatur batas waktu pada metode socket recv python. Bagaimana cara melakukannya?
Saya perlu mengatur batas waktu pada metode socket recv python. Bagaimana cara melakukannya?
Jawaban:
Pendekatan tipikal adalah menggunakan select () untuk menunggu hingga data tersedia atau hingga batas waktu terjadi. Telepon hanya recv()
jika data benar-benar tersedia. Untuk amannya, kami juga menyetel soket ke mode non-pemblokiran untuk menjamin bahwa recv()
tidak akan pernah memblokir tanpa batas. select()
juga dapat digunakan untuk menunggu lebih dari satu soket dalam satu waktu.
import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
data = mysocket.recv(4096)
Jika Anda memiliki banyak deskriptor file yang terbuka, poll () adalah alternatif yang lebih efisien untuk select()
.
Pilihan lain adalah mengatur batas waktu untuk semua operasi pada soket yang digunakan socket.settimeout()
, tetapi saya melihat bahwa Anda secara eksplisit menolak solusi itu di jawaban lain.
select
itu bagus, tetapi bagian di mana Anda mengatakan "Anda tidak bisa" menyesatkan, karena memang ada socket.settimeout()
.
select
- jika Anda menjalankan mesin Windows, select
bergantung pada pustaka WinSock, yang memiliki kebiasaan untuk kembali segera setelah beberapa data tiba, tetapi tidak harus semuanya . Jadi, Anda perlu memasukkan loop untuk terus menelepon select.select()
hingga semua data diterima. Bagaimana Anda tahu bahwa Anda telah mendapatkan semua data (sayangnya) terserah Anda untuk mengetahuinya - ini mungkin berarti mencari string terminator, sejumlah byte, atau hanya menunggu waktu tunggu yang ditentukan.
ready[0]
hanya salah jika tidak ada bagian dalam respons server?
disana socket.settimeout()
select
lebih disukai ketika solusi ini adalah satu liner (lebih mudah dirawat, lebih sedikit risiko dalam penerapan yang salah) dan menggunakan pilihan di bawah tenda (penerapannya sama dengan jawaban @DanielStuzbach).
Seperti yang disebutkan, keduanya select.select()
dan socket.settimeout()
akan berhasil.
Perhatikan bahwa Anda mungkin perlu menelepon settimeout
dua kali untuk kebutuhan Anda, misalnya
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("",0))
sock.listen(1)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()
# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)
.settimeout()
lebih dari sekali, Anda dapat memanggil setdefaulttimeout()
metode ini sejak awal.
Waktu tunggu yang Anda cari adalah batas waktu soket sambungan, bukan waktu tunggu soket utama, jika Anda menerapkan sisi server. Dengan kata lain, ada waktu tunggu lain untuk objek soket sambungan, yang merupakan keluaran socket.accept()
metode. Karena itu:
sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5) # This is the one that affects recv() method.
connection.gettimeout() # This should result 5
sock.gettimeout() # This outputs None when not set previously, if I remember correctly.
Jika Anda menerapkan sisi klien, itu akan sederhana.
sock.connect(server_address)
sock.settimeout(3)
Seperti yang disebutkan dalam balasan sebelumnya, Anda dapat menggunakan sesuatu seperti: .settimeout()
Misalnya:
import socket
s = socket.socket()
s.settimeout(1) # Sets the socket to timeout after 1 second of no activity
host, port = "somehost", 4444
s.connect((host, port))
s.send("Hello World!\r\n")
try:
rec = s.recv(100) # try to receive 100 bytes
except socket.timeout: # fail after 1 second of no activity
print("Didn't receive data! [Timeout]")
finally:
s.close()
Saya harap ini membantu!!
Anda dapat menggunakan socket.settimeout()
yang menerima argumen integer yang mewakili jumlah detik. Misalnya, socket.settimeout(1)
akan menyetel waktu tunggu ke 1 detik
coba ini menggunakan C. yang mendasari.
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
SO_RCVTIMEO
dan SO_SNDTIMEO
.
2
dan mengapa 100
? Berapakah nilai batas waktu? Di unit apa?
timeval = struct.pack('ll', sec, usec)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
usec = 10000 berarti 10 ms
#! /usr/bin/python3.6
# -*- coding: utf-8 -*-
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(5)
PORT = 10801
s.bind(('', PORT))
print('Listening for broadcast at ', s.getsockname())
BUFFER_SIZE = 4096
while True:
try:
data, address = s.recvfrom(BUFFER_SIZE)
except socket.timeout:
print("Didn't receive data! [Timeout 5s]")
continue
Berteriak kepada: https://boltons.readthedocs.io/en/latest/socketutils.html
Ini menyediakan soket buffer, ini menyediakan banyak fungsi yang sangat berguna seperti:
.recv_until() #recv until occurrence of bytes
.recv_closed() #recv until close
.peek() #peek at buffer but don't pop values
.settimeout() #configure timeout (including recv timeout)