Python: сокет и потоки?
У меня проблема конструкции:
У меня есть два потока, поток heartbeat/control и поток messagehandler.
оба используют один и тот же сокет, однако поток messageHandler только отправляет сообщения и никогда не получает. Поток heartbeat отправляет и получает (получает сообщения и реагирует на удары сердца).
проблема в том, что я не уверен, если это безопасно. Нет никакого механизма, я сам, реализованный, чтобы увидеть, используется ли сокет. таким образом, совместное использование сокета через python автоматически безопасно или нет?
кроме того, если это не так, причина, по которой я помещаю их в отдельный поток, заключается в том, что сердцебиение более важно, чем обработка сообщений. Это означает, что если он затоплен сообщениями, ему все равно нужно сделать сердцебиение. Итак, если мне нужно реализовать болт, есть ли я могу определить приоритет, если моему сердцебиению / контрольному потоку нужно отправить сердцебиение?
4 ответов
к сожалению, сокет, разделяемый несколькими потоками, не является потокобезопасным.Подумайте о буфере два потока работают без блокировки.
обычный способ реализации - с двумя сокетами, как и ftp.гнездо cmd и гнездо msg.
Если вы хотите реализовать это одним сокетом,вы можете поместить разные типы msgs в разные очереди, а с третьим потоком потребляет очередь и отправляет их через единственный сокет.
таким образом,вы можете контролировать сердцебиение msg priory к данным msg.
лучший способ вместо использования третьего потока-использовать threading.Lock()
для защиты ресурса сокета, поскольку это устраняет необходимость в третьем потоке. У вас меньше накладных расходов и меньше задержки, чем если бы у вас был третий поток.
import threading
lock = threading.Lock()
def sendfunction(sock, data):
with lock:
sock.send(data)
вы можете вызвать это из любого из ваших потоков, но только один поток за раз будет разрешено вызывать sock.send
. Когда поток достигает блокировки, которая уже заблокирована другим потоком, он будет спать, пока другой поток не освободит блокировку, тогда он приобретет блокировку и процесс повторится.
модуль резьбы содержит Lock
, RLock
и Condition
- все это очень полезно при работе с несколькими потоками, и вы найдете это стоит вашего времени, чтобы ознакомиться с ними и их использования.
вы можете включить сердцебиение в обработку сообщений, проверив текущее время с последним разом, когда вы отправили сердцебиение перед обработкой каждого сообщения, и это предотвратит быть затопленным сообщениями, вызывающими сердцебиение, которое не будет отправлено. Проблема в том, что если ваш код обработки сообщений не запускается, то сердцебиения не будут отправлены. Вы можете облегчить это, если ваш код обработки сообщений получит фиктивное сообщение на интервале, чтобы он мог проверить, нужно ли ему отправлять сердцебиение и просто игнорировать фиктивное сообщение.
вы должны попытаться использовать потоки экономно (стремиться к одному потоку), однако в вашем случае поток, вероятно, будет в порядке, так как он будет тратить большинство это время спит. Однако вы не должны использовать поток демона, потому что они не завершают работу должным образом. Хотя ущерб может быть несуществующим в вашем случае, если он не был должным образом выключен, он все еще может вызвать какой-то тип ошибки (сообщение об ошибке), который выглядит плохо.
Я не согласен с методом множественных сокетов, поскольку я думаю, что это фактически усложнит ситуацию. Вы найдете множество типов сетевых служб / приложений, которые включают в себя сердцебиение и сообщения в один байтовый поток сокетов.
Я не знаю, как расставить приоритеты на уровне Python.
поэтому я бы предложил использовать 2 процесса, а не потоки, и расставлять приоритеты на уровне ОС. В Unix вы можете использовать ОС.приятно () сделать это.
вам нужно будет использовать 2 сокета, и ваша проблема совместного использования будет решена одновременно.
Если оба потока являются клиентскими потоками, рекомендуется открыть два клиентских сокета один для сервера для сердцебиения, а другой для связи.