Как очистить сокет в 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-пакетов я сделал следующее:

  1. после создания сокета, настройки и привязки, я использую socket.settimeout(). Примечание документация setblocking() дает некоторую информацию, которая из settimeout() не делает-если вы хотите, чтобы ваши операции сокета блокировать, вы должны просто использовать settimeout() установить тайм-аут. setblocking() просто ставит бесконечный тайм-аут на него. (У меня была ошибка вызова settimeout() следовал по setblocking(1).)

  2. мой функция "опорожнение буфера" - это просто ("слушатель" - мой сокет):

    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