Изящно останавливать сокет во время блокировки вызова socket.recv () - PullRequest
0 голосов
/ 30 мая 2019

У меня есть программа, которая работает на 2 темы.Основной поток для своей собственной работы, а другой поток продолжает вызывать recv() на сокете UDP.

В основном, структура кода выглядит следующим образом:

done = False

def run_sock():
   sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   sock.bind(('localhost', 12345))
   while not done:  # receive data until work done
        data = sock.recv(1500)
        print(data)
   sock.close()

thread = threading.Thread(target=run_sock, daemon=True)
thread.start()

# Main thread
while not done:
    ... # Do work here
    if some_condition:  # Stop running, thread should as well
        done = True

thread.join()

Я хочу закрытьсокет, когда основной поток изменяется done на True, но когда это происходит, сокет все еще находится в своем текущем блокирующем вызове recv, и он должен получить другое сообщение, прежде чем он окончательно остановится.

Есть ли способ изящно закрыть сокет (без необходимости обрабатывать ошибки)?Я пробовал sock.shutdown(socket.SHUT_RDWR), sock.setblocking(False), но все они вызывают ошибки.

1 Ответ

0 голосов
/ 30 мая 2019

Так что sock.recv(1500) будет блокироваться, пока не получит что-то .Если он ничего не получает, он ждет.

Но если вы установите тайм-аут, то это ожидание периодически вызывает исключение, и вы можете делать другие вещи (например, смотреть на флаг «Готово»), прежде чем пытаться читать снова.

sock.settimeout(1.0)
sock.bind(...)

while not done:
    try:
        data = sock.recv(1500)
    except timeout:
        continue
sock.close()

Конечно, если удаленный конец закрывает другое соединение.Затем вам нужно взглянуть на data, чтобы увидеть, пусто ли оно.

while not done:
    try:
        data = sock.recv(1500)
        if not data:
            break
    except timeout:
        continue
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...