Как очистить сокет в python?
Мне нужно очистить данные в сокете (убедившись, что получать нечего). К сожалению, для этого нет функции в модуле сокета python.
я реализовал что-то так:
def empty_socket(sock):
"""remove the data present on the socket"""
input = [sock]
while 1:
inputready, o, e = select.select(input,[],[], 0.0)
if len(inputready)==0: break
for s in inputready: s.recv(1)
что вы думаете? Есть ли лучший способ сделать это?
Update: я не хочу изменять тайм-аут сокета. Почему я предпочитаю выбор чтению.
Update: исходный вопрос использовал термин "флеш". Кажется, что "пустой" - лучший термин.
обновление - 2010-02-27 : Я заметил ошибку, когда пара закрылась. Inputready всегда заполняется сокетами. Я исправил это, добавив максимальное количество циклов. Есть ли лучшее решение?
5 ответов
Если под "флеш" вы имеете в виду выбросить любые ожидающие входящие данные, то вы можете либо использовать select (), как вы это делаете, либо установить сокет на неблокирующийся и читать в цикле, пока вы не закончите данные.
также обратите внимание, что (из manpage Linux):
в Linux select () может сообщить о дескрипторе файла сокета как " готов для чтения", хотя тем не менее последующие блоки чтения. Этот может, например, произойти, когда данные прибыли, но по экспертиза неправильная контрольная сумма и отбрасывается. Могут быть и другие обстоятельства, при которых файловый дескриптор ложно сообщается как готовый. Таким образом, может быть безопаснее использовать O_NONBLOCK на сокетах, которые должны не перекрывать.
ложное уведомление о готовности для выбора системного вызова
и, как было отмечено другими, "флеш"обычно относится к выходу.
используя select.select
хорошая практика, как указано в Программирование сокетов HOWTO. Вам нужно будет установить сокет как неблокирующий, используя sock.setblocking(0)
.
просто комментарий о номенклатуре:flush
обычно ассоциируется с выход операции.
для UDP-пакетов я сделал следующее:
после создания сокета, настройки и привязки, я использую
socket.settimeout()
. Примечание документацияsetblocking()
дает некоторую информацию, которая изsettimeout()
не делает-если вы хотите, чтобы ваши операции сокета блокировать, вы должны просто использоватьsettimeout()
установить тайм-аут.setblocking()
просто ставит бесконечный тайм-аут на него. (У меня была ошибка вызоваsettimeout()
следовал поsetblocking(1)
.)-
мой функция "опорожнение буфера" - это просто ("слушатель" - мой сокет):
def FlushListen(self): while 1: try: PacketBytes = self.__Listener.recv(1024) except: break;
С тайм-аутом 1 секунды, это прочитает все UDP-пакеты, а затем вернет 1 секунду после того, как нет данных.
в моем случае я использую его, чтобы просто говорить между двумя программами на одном ПК, чтобы я мог легко снизить свой тайм-аут, но скорость не проблема, поэтому я в порядке с этим.
согласно некоторым из ссылок, опубликованных другими, это должно работать с потоками данных.
не можем ли мы просто продолжать читать, пока буфер не опустеет?
def clear_buffer(sock):
try:
while sock.recv(1024): pass
except:
pass
не уверен, что это сработает, но вы можете прикрепить файловый объект к файловому дескриптору сокета и вызвать flush()
метод объекта file:
import os
file_obj = os.fdopen(your_socket.fileno())
file_obj.flush()
это не будет работать в Windows, потому что дескриптор, возвращенный fileno()
невозможно передать в os.fdopen()
в Windows