Yanıtlar:
Tipik yaklaşım, veri kullanılabilir olana kadar veya zaman aşımı gerçekleşene kadar beklemek için select () kullanmaktır . Yalnızca recv()
veriler gerçekten mevcut olduğunda arayın . Güvende olmak için, recv()
süresiz olarak asla bloke olmayacağını garanti etmek için soketi engellemesiz moda da ayarladık . select()
aynı anda birden fazla soket beklemek için de kullanılabilir.
import select
mysocket.setblocking(0)
ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
data = mysocket.recv(4096)
Çok sayıda açık dosya tanımlayıcınız varsa, anket () 'e göre daha etkili bir alternatiftir select()
.
Diğer bir seçenek, kullanarak soket üzerindeki tüm işlemler için bir zaman aşımı ayarlamaktır socket.settimeout()
, ancak bu çözümü başka bir yanıtta açıkça reddettiğinizi görüyorum.
select
iyidir, ancak "yapamazsın" dediğiniz kısım yanıltıcıdır, çünkü vardır socket.settimeout()
.
select
- bir Windows makinesinde çalışıyorsanız, bazı veriler gelir select
gelmez geri dönme alışkanlığı olan WinSock kitaplığına güvenir , ancak hepsi zorunlu değildir . Bu nedenle, tüm veriler alınana kadar aramaya devam etmek için bir döngü eklemeniz gerekir . Tüm verileri aldığınızı nasıl bildiğiniz (maalesef) size kalmış - bu bir sonlandırıcı dizge, belirli sayıda bayt aramak veya sadece belirli bir zaman aşımını beklemek anlamına gelebilir. select.select()
ready[0]
sunucunun yanıt olarak ortada ceset yok eğer sadece yanlış?
select
Bu çözüm tek satırlık bir çözüm olduğunda (bakımı daha kolay, yanlış uygulamada daha az risk) ve başlık altında select kullandığında (uygulama @DanielStuzbach yanıtıyla aynıdır) neden kullanılan çözümün tercih edildiğinden emin değilim .
As hem söz select.select()
ve socket.settimeout()
çalışacaktır.
settimeout
İhtiyaçlarınız için iki kez aramanız gerekebileceğini unutmayın , örneğin
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()
kereden fazla aradığınızda, setdefaulttimeout()
yöntemi ilk etapta çağırabilirsiniz .
Sunucu tarafını uygularsanız, aradığınız zaman aşımı, bağlantı soketinin zaman aşımıdır, birincil soketler değil. Başka bir deyişle, socket.accept()
yöntemin çıktısı olan bağlantı soketi nesnesi için başka bir zaman aşımı vardır . Bu nedenle:
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.
İstemci tarafını uygularsanız, bu basit olacaktır.
sock.connect(server_address)
sock.settimeout(3)
Önceki yanıtlarda belirtildiği gibi, aşağıdaki gibi bir şey kullanabilirsiniz: .settimeout()
Örneğin:
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()
Umarım bu yardımcı olur!!
socket.settimeout()
Saniyelerin sayısını temsil eden bir tamsayı bağımsız değişkenini kabul eden seçeneği kullanabilirsiniz . Örneğin socket.settimeout(1)
, zaman aşımını 1 saniyeye ayarlayacak
bunu deneyin, temeldeki C'yi kullanır.
timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
SO_RCVTIMEO
ve SO_SNDTIMEO
.
2
ve neden 100
? Zaman aşımı değeri nedir? Hangi birimde?
timeval = struct.pack('ll', sec, usec)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
usec = 10000, 10 ms anlamına gelir
#! /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
Şu kişiye seslenin: https://boltons.readthedocs.io/en/latest/socketutils.html
Arabelleğe alınmış bir soket sağlar, bu, aşağıdakiler gibi birçok yararlı işlevsellik sağlar:
.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)