Python разрывает строку после первого символа - PullRequest
2 голосов
/ 30 апреля 2019

Моя программа на сокете Python прерывается после первого символа при получении однострочной строки.Программа сокетов работает на Raspberry Pi, а также на клиенте и Java.Вот мой код для сокета

HOST = ''
PORT = 8888

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')

try:
    s.bind((HOST, PORT))
except socket.error as socketError:
    print('socket binding failed, ', socketError)
    print('Exiting...')
    sys.exit(0)

print('Socket binding complete')

s.listen(1)
print('Socket listening for connection...')

conn, addr = s.accept()

print('connected to ',addr[0])

try:
    while True:
        data = conn.recv(1024).decode('utf-8')
        print('value received',data)

except Exception as loopException:
    print("Exception occurred in loop, exiting...",loopException)
finally:
    s.close()

Вот так я отправляю данные из java

socket = new Socket(dstAddress, Integer.parseInt(dstPort));
os = new DataOutputStream(socket.getOutputStream());
os.writeBytes("Connection-Ready to receive commands");

Это то, что я получаю в терминале

value received C
value received onnected-Ready to receive commands

Кто-нибудьзнаете, почему он так себя ведет?

Ответы [ 2 ]

3 голосов
/ 30 апреля 2019

Вам нужно читать в цикле, пока вы не получите все входные данные.Вам нужен способ узнать, когда у вас есть все входные данные.

Если клиент пишет, а затем закрывает сокет, вы можете читать, пока не доберетесь до EOF.Если клиент не закрывает сокет, вам нужен какой-то способ узнать, сколько читать.Самое простое - заставить клиента отправить длинное слово перед отправкой символов.Вы читаете длину, а затем читаете столько символов.

Задержка - это хак, который пока может работать, но не надежен.Если в вашей сети наблюдается некоторое замедление, ваш код может прерваться.

Из ваших выводов видно, что вы закрываете поток на стороне клиента, даже если вы этого не показываете.Итак, вам просто нужно буферизовать все ваши данные, пока вы не достигнете конца потока.Это должно работать:

buffer = b''
try:
    while True:
        data = conn.recv(1024)
        if not data:
            break
        buffer += data
except Exception as loopException:
    print("Exception occurred in loop, exiting...", loopException)
finally:
    s.close()

print('value received', buffer.decode('utf-8'))

Я думаю, что это будет работать.У меня нет связи, чтобы попробовать это, но моей IDE это нравится.Я не настолько знаком с потоками байтов Python 3.Если это не совсем работает, вы все равно должны получить представление здесь.

2 голосов
/ 30 апреля 2019

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

Это также означает, что вам необходимо указать способ получения полного сообщения.Отправьте длину сообщения перед сообщением или прочитайте до новой строки.

...