Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 4, 2023 10:17:50

IvanPletnev
Зарегистрирован: 2023-08-04
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Закрыть сокет и завершить поток из соседнего потока

Всем привет!
Есть поток - функция, в которой сокет принимает сообщения. Для того, чтобы отслеживать таймаут, в этом потоке я запускаю еще один поток timeoutTimer , выполняющий функцию таймера, который вызывает self.tmr_callback по истечении таймаута. Так вот, во-первых, если я пытаюсь в коллбэке закрыть сокет, он закрывается, но клиент почему-то не реагирует на это, считает, что соединение открыто, а во-вторых, как сделать так, чтобы при срабатывании таймера корректно закрыть соединение и выйти из потока listen_to_client?
Помогите новичку, плиз!

            listenThread = Thread(
                target=self.listen_to_client,
                args=(client, address, self.on_receive_callback, self.on_disconnected_callback)
            )
 
def tmrCallBack (client):
    client.close()
    print ('Timer callback called')
 
 def listen_to_client(self, client, address, on_receive_callback, on_disconnected_callback):
        # set a buffer size ( could be 2048 or 4096 / power of 2 )
        size = 1024*1024
        timeoutTimer = WatchdogTimer (5.0, self.tmr_callback, args=(client,), daemon = True)
        timeoutTimer.start()
        while True:
            try:
                d = client.recv(size)
                self.currentClient = client
                timeoutTimer.restart()
                if d:
                    #messages = d.split(b'\n\r')
                    messages = d.split(b'\0')
                    for data in messages:
                        if data:
                            data = data.decode('utf-8')
                            if self.debug:
                                print(datetime.now(), self.serverName, 'CLIENT Data Received', address)
                                if not self.debug_data:
                                    print('\n')
 
                            if self.debug_data:
                                print(data, '\n')
 
                            if on_receive_callback:
                                try:
                                    on_receive_callback(client, address, data)
                                except Exception as e:
                                    if self.debug:
                                        print(datetime.now(), 'CLIENT Receive Callback Failed:', data, '\n', e, '\n')
                else:
                    raise ValueError('CLIENT Disconnected')
                    
            except Exception as e:
                if self.debug:
                    print(datetime.now(), e, client, '\n')
                timeoutTimer.cancel()
                client.close()
                client_index = self.clients.index(client)                
                self.clients.pop(client_index)
                if on_disconnected_callback:
                    try:
                        on_disconnected_callback(client, address)
                    except Exception as e:
                        print('on_close_callback failed\n', e, '\n')
                return False

Офлайн

#2 Авг. 4, 2023 12:37:00

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9863
Репутация: +  853  -
Профиль   Отправить e-mail  

Закрыть сокет и завершить поток из соседнего потока

IvanPletnev
Есть поток - функция, в которой сокет принимает сообщения.
Да это просто ерунда какая-то. Вложения в коде должны быть не больше трёх уровней. Если у тебя больше уровней, то ты не знаешь, как код писать. А тема многопоточных программ сложная. Так что ты заведомо обрёк себя на проблемы.

Так что можешь смело стирать всё это и спрашивать свой вопрос: как написать то-то и то-то, чтобы оно делало то-то и то-то.



Отредактировано py.user.next (Авг. 4, 2023 12:38:15)

Офлайн

#3 Авг. 4, 2023 13:57:30

IvanPletnev
Зарегистрирован: 2023-08-04
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Закрыть сокет и завершить поток из соседнего потока

py.user.next
Хорошо. Я согласен, что не знаю, как правильно писать код. Поэтому и обратился на форум для новичков. Мне нужно контролировать таймаут по приёму сообщений, и если он наступает, закрывать соединение. Если подскажете, как это сделать, буду крайне благодарен.

Офлайн

#4 Авг. 4, 2023 14:03:30

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9863
Репутация: +  853  -
Профиль   Отправить e-mail  

Закрыть сокет и завершить поток из соседнего потока

IvanPletnev
Мне нужно контролировать таймаут по приёму сообщений, и если он наступает, закрывать соединение.
Сделай скрипт новый, в котором одно соединение, в котором нет многопоточности. Элементарнейший скрипт с минимумом всего. И вот в нём попробуй поконтролировать таймаут. Когда у тебя не получится это сделать, тогда ты и поймёшь, что дело не в многопоточности.



Отредактировано py.user.next (Авг. 4, 2023 14:05:33)

Офлайн

#5 Авг. 4, 2023 15:04:27

IvanPletnev
Зарегистрирован: 2023-08-04
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Закрыть сокет и завершить поток из соседнего потока

py.user.next
И вот в нём попробуй поконтролировать таймаут.
Кажется, я понял, что нужно делать. Использовать свойство socket.timeout. И ловить исключение по его срабатыванию

Офлайн

#6 Авг. 4, 2023 23:38:15

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1352
Репутация: +  118  -
Профиль   Отправить e-mail  

Закрыть сокет и завершить поток из соседнего потока

  
import threading
import time
def worker():
    for i in range(4):
        print(i)
        time.sleep(1)
def main():
    timeout = 3
    thread = threading.Thread(target=worker)
    thread.daemon = True 
    thread.start()
    thread.join(timeout)
    if thread.is_alive():
        print('Поток остановлен принудительно')
    else:
        print("Поток отработал")
if __name__ == "__main__":
    main()

Онлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version