Создание «объекта типа байта» в Python 3 - PullRequest
0 голосов
/ 17 мая 2018

У меня в настоящий момент работает сервер под этим кодом:

    import socket                   


port = 60000                  
s = socket.socket()             
host = socket.gethostname()    
s.bind((host, port))           
s.listen(1)                     

print ('Server listening....')

while True:
    conn, addr = s.accept()     
    print ('Got connection from', addr)
    data = conn.recv(1024)
    print('Server received', repr(data))

    filename='mytext.txt'
    f = open(filename,'rb')
    l = f.read(1024)
    while (l):
       conn.send(l)
       print('Sent ',repr(l))
       l = f.read(1024)
    f.close()

    print('Done sending')
    conn.send('Thank you for connecting')
    conn.close()

И клиент работает под этим кодом:

import socket

    s = socket.socket()              
host = socket.gethostname()      
port = 60000                    

    s.connect((host, port)) 
    s.send('Test')

with open('received_file', 'wb') as f:
    print ('file opened')
    while True:
        print('receiving data...')
        data = s.recv(1024)
        print('data=%s', (data))
        if not data:
            break
        # write data to a file
        f.write(data)

    f.close() 
print('Successfully get the file') 
s.close()

     print('connection closed')

Проблема в том, что когда клиент пытается отправитьданные, в которых говорится, что отправляемые данные должны быть объектами байтового типа (здесь показан код ошибки: https://gyazo.com/97ef155f6809a801b02f381670895a2b.). Я искал в Интернете ответ о том, как создать объект байтового типа внутри Python 3, но яне смогли найти ничего, что сработало.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Если вы просто отправляете литералы, вы можете просто использовать литерал bytes вместо литерала str, поставив перед ним префикс b.Вместо этого:

sock.send('Hello')

… просто сделайте это:

sock.send(b'Hello')

Если вы отправляете строковые переменные, вам нужно будет encode их для отправки, ивероятно decode их при получении.Вместо этого:

sock.send(msg)
resp = sock.recv(4096)

… do:

sock.send(msg.encode('ascii')
resp = sock.recv(4096).decode('ascii')

Если вы хотите отправлять не-ASCII строки, вам нужно выбрать кодировку.Если у вас нет веских причин поступить иначе, используйте UTF-8.


Еще одна вещь, которую нужно иметь в виду: сокеты TCP - это просто потоки байтов, а не сообщений, и их можно произвольно разделитьв пакеты.Когда вы можете recv(1024), вы можете получить только часть того, что отправила другая сторона с send.Это, вероятно, очевидно, если вы отправляете строки длиннее 1024 байта, но даже для более коротких строк это может произойти.Или, если вы не строго чередуете отправку и получение, вы можете объединить несколько отправок в один прием.И если вы отправите hello, а затем world и получите их как helloworld, у вас нет возможности узнать, что произошло, или как разделить их на части.

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

Итак,вам нужен протокол, который описывает, где заканчивается одно сообщение и начинается другое.У меня пост в блоге , который объясняет некоторые опции и показывает, как их реализовать.

Но если вы просто отправляете понятные человеку строки в качестве сообщений, и эти строки никогда не будут содержать переводы строк.Простейший протокол - это просто строка для каждого сообщения, точно так же, как вы пишете текстовый файл.И посмотрите на socket.makefile: он дает вам что-то, что действует как файл, обрабатывает одну строку для каждого протокола сообщений, а также автоматически обрабатывает части encode и decode.Итак, вместо этого:

sock.send(msg.encode('utf-8'))
resp = sock.recv(1024).decode('utf-8')

… вы просто используете makefile для получения читаемых и записываемых файловых объектов, затем выполните:

wf.write(msg + '\n')
resp = next(rf)

… и тогда вы ненадо беспокоиться о том, как буферизовать получаемые данные и разбивать их на сообщения.

0 голосов
/ 17 мая 2018

Измените строку кода клиента:

s.send('Test')

на:

s.send(b'Test')

Более подробную информацию о socket.send () можно найти в https://docs.python.org/3/library/socket.html.

...