Python Socket Как получить непрерывный поток данных с помощью recv в потоке?

Итак, я пытаюсь написать программу, которая получает непрерывный поток данных с сервера в потоке. Данные, отправляемые с сервера, всегда очень короткие, но имеют разную длину.

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

Это часть сокета моего кода:

client = socket(AF_INET, SOCK_STREAM)

def connectToServer(host, port):
    global client
    try:
        client.connect((host, port))
        connectionResult = client.recv(2048).decode()
        if connectionResult == 'succesfull connection':
            return connectionResult
        else:
            return 'connection failed'

    except:
        return 'connection failed'

# This function is ran in a thread (from another module)
def getUpdatesFromServer(updateQueue):
    global client
    while True:
        receivedUpdate = client.recv(10000).decode()
        if receivedUpdate == 'server went down':
            updateQueue.put('server went down')

И это код, который запускает поток:

getUpdatesFromServerThread = Thread(target=ServerConnect.getUpdatesFromServer, args=(GameState.screenUpdateQueue,))
getUpdatesFromServerThread.daemon = True
getUpdatesFromServerThread.start()

Здесь вызывается функция connectToServer (первое, что происходит при запуске клиента):

connectionOutcome = ServerConnect.connectToServer(host, port)
if connectionOutcome == 'succesfull connection':
    startGame()
else:
    print('\n\nFailed to connect to the server. Please check your internet connection. If your internet connection is okay, it probably means the server is down and you should wait for a while.\n\n')

А вот функция startGame:

def startGame():
    print('You have been succesfully connected to the server.')
    getUpdatesFromServerThread = Thread(target=ServerConnect.getUpdatesFromServer, args=(GameState.screenUpdateQueue,))
    getUpdatesFromServerThread.daemon = True
    getUpdatesFromServerThread.start()
    screenUpdateThread = Thread(target=doScreenUpdates)
    screenUpdateThread.daemon = True
    screenUpdateThread.start()
    sleep(1)
    MainGameScreen.main()
    # When the eventloop stops, this is ran and sends a disconnect signal to the server, which closes the connection (which does work)
    sleep(0.5)
    ServerConnect.sendCommandToServer('disconnect')

Заранее спасибо!

Изменить: я нашел проблему. Я думал, что сервер отправляет данные, но на самом деле это не так, он просто не выдавал никаких сообщений об ошибках, поэтому я предположил, что это работает.


person MiloTier    schedule 08.08.2019    source источник
comment
Откуда вы знаете, что ничего не получаете? Вы проверяете receivedUpdate, потому что в вашем текущем примере вы никуда его не отправляете.   -  person JohanL    schedule 08.08.2019
comment
Что происходит, когда вызывается recv (блокирующий вызов), он остается там в ожидании данных? Я считаю, что вам нужно разместить больше журналов отладки, например. перед вызовом recv, чтобы убедиться, что поток запущен. Также подключение к серверу вызывается до запуска вашего потока. Вы проверяли, действительно ли на сокете есть данные? Сделайте netstat -an и проверьте его. Вы увидите Rec-Q Send-Q   -  person PraveenB    schedule 08.08.2019
comment
Да, я уверен, что он ничего не получает. Я проверил, и данные не принимаются, и этот поток вызывается. Я также уверен, что сервер отправляет данные. И на что мне следует обращать внимание при использовании nestat -an?   -  person MiloTier    schedule 08.08.2019
comment
Он начинает работать, когда вы не используете поток? Украсьте пути выполнения вашего кода отпечатками, чтобы вы знали, куда он попадает в основной ветке и в потоке? Полученный поток ничего не сообщает, если сообщение не «сервер вышел из строя», так как вы узнаете, что ничего не получаете? Сравнение возвращаемого значения из recv со строками определенной длины может работать некоторое/большую часть времени, но очень хрупкое, потому что сокет может разделять или объединять данные произвольным образом - вам нужен правильный способ обработки этого, как только вы получите эту часть функциональности работающий.   -  person barny    schedule 08.08.2019
comment
Нет, к сожалению, это не сработало. Я пытался использовать if len(receivedUpdate) > 0:, но ничего не произошло   -  person MiloTier    schedule 08.08.2019
comment
безпоточность не работала? настройте свой собственный замещающий сервер (в Python это не сложно, я уверен, что есть много примеров), а затем вы можете устранить вопрос «возможно, сервер ничего не отправляет».   -  person barny    schedule 08.08.2019
comment
Были ли вызваны connectToServer — добавьте это к своему вопросу.   -  person barny    schedule 08.08.2019
comment
На самом деле я уже использую самодельный сервер, сделанный с помощью крутилки, работающий на моем локальном хосте. И я уверен, что это отправка данных, потому что подтверждение отправляется так же, как и когда не работает.   -  person MiloTier    schedule 08.08.2019
comment
... Я знаю, что общая проблема с функцией recv заключается в том, что она иногда разделяет данные... Сеть разделяет данные, recv покорно дает вам все, что есть в наличии, когда вы об этом просите. Ваш код сразу выходит из строя сразу в connectionResult = client.recv(2048).decode() и продолжает работать неправильно в receivedUpdate = client.recv(10000).decode(). Вы не понимаете, что SOCK_STREAM (TCP) — это протокол потоковой передачи, вместо этого вы притворяетесь, что это протокол сообщений. Это не так, и это не сработает.   -  person President James K. Polk    schedule 08.08.2019
comment
Хорошо, но что вы предлагаете мне использовать вместо этого?   -  person MiloTier    schedule 08.08.2019
comment
Ну, я искал какое-то время, но не могу найти ответ, который подходит для моей конкретной ситуации. Я не могу найти другого вопроса, в котором recv ничего не возвращает.   -  person MiloTier    schedule 08.08.2019
comment
Вот достойный пример.   -  person President James K. Polk    schedule 08.08.2019
comment
Хм, я не думаю, что проблема в функции. Я пробовал все три примера, и ни один из них не возвращает никаких данных. Кажется, я где-то ошибся, но не могу понять, где.   -  person MiloTier    schedule 09.08.2019