Ошибка типа: требуется объект, подобный байтам, а не ‘str’

#python #python-3.x #sockets #typeerror

#python #python-3.x #сокеты

Вопрос:

Ниже приведен код, который пытается изменить входные данные, предоставленные пользователем, с помощью сокетов:

 from socket import *

serverName = '127.0.0.1'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_DGRAM)
message = input('Input lowercase sentence:')
clientSocket.sendto(message,(serverName, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print (modifiedMessage)
clientSocket.close()
  

Когда я выполняю его и предоставляю ввод, возникает следующая ошибка:

 Input lowercase sentence:fdsgfdf
Traceback (most recent call last):
  File "C:srinath filesNETWORKSUDPclient.py", line 6, in <module>
    clientSocket.sendto(message,(serverName, serverPort))
TypeError: a bytes-like object is required, not 'str'
  

Что я могу сделать, чтобы решить эту проблему?

Комментарии:

1. Первый аргумент ( message ) должен быть байтами, но вы передаете строку. Вы должны закодировать его перед отправкой, например message.encode('utf-8')

2. но дело в том, что мне нужно передать на сервер строку, а не байт

3. из импорта сокета * Имя_сервера = ‘hostname’ ServerPort = 12000 clientSocket = сокет(AF_INET, SOCK_DGRAM) сообщение = ввод (‘Ввод строчного предложения:’) сообщение.закодировать(‘utf-8’) clientSocket. sendto(сообщение,(имя_сервера, ServerPort)) Модифицированное сообщение, адрес сервера = clientSocket. recvfrom(2048) print (modifiedMessage) clientSocket.close()

4. То, что передается по проводу, всегда является байтами. Сервер должен иметь возможность каким-то образом понимать эти байты.

5. Это потому, что message все еще является строкой. Вам нужно что-то вроде clientSocket.sendto(message.encode('utf-8'), ...)

Ответ №1:

Этот код подходит для Python 2. Но в Python 3 это приводит к ошибке кодирования битов. Я пытался создать простой TCP-сервер и столкнулся с той же проблемой. Кодирование решает эту проблему. Попробуйте это с помощью sendto команды.

 clientSocket.sendto(message.encode(),(serverName, serverPort))
  

Аналогично вы должны использовать .decode() для получения данных на стороне сервера UDP, если вы хотите распечатать их точно так, как они были отправлены.

Комментарии:

1. увеличит ли кодирование и декодирование с обеих сторон соединения задержку? Если это так, будет ли python2 на самом деле быстрее отправлять данные, чем python3

2. На мой взгляд, это не повлияет на производительность, такую как задержка и т.д. Однако я сам не пробовал экспериментировать с ним, поэтому я не могу быть уверен в этом.

3. python сделал это только для поддержки emoji 🌿 в своем собственном классе String? Я думаю, это хорошо для интернационализации re: message.encode('utf-16') и 💩

Ответ №2:

Кодирование и декодирование могут решить эту проблему в Python 3:

На стороне клиента:

 >>> host='127.0.0.1'
>>> port=1337
>>> import socket
>>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> s.connect((host,port))
>>> st='connection done'
>>> byt=st.encode()
>>> s.send(byt)
15
>>>
  

На стороне сервера:

 >>> host=''
>>> port=1337
>>> import socket
>>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> s.bind((host,port))
>>> s.listen(1)
>>> conn ,addr=s.accept()
>>> data=conn.recv(2000)
>>> data.decode()
'connection done'
>>>
  

Комментарии:

1. Смотрите также nedbatchelder.com/text/unipain.html чтобы понять, почему это изменилось в Python 3.

Ответ №3:

Немного кодирования может решить эту проблему:

На стороне клиента:

 message = input("->")
clientSocket.sendto(message.encode('utf-8'), (address, port))
  

На стороне сервера:

 data = s.recv(1024)
modifiedMessage, serverAddress = clientSocket.recvfrom(message.decode('utf-8'))
  

Комментарии:

1. Ваш клиент не будет работать: для отправки требуется 3 параметра, сообщение, адрес сервера и соответствующий порт

2. Сообщение, адрес и порт. Мне кажется, что 3 параметра и работает на моем! 🙂

Ответ №4:

Просто замените параметр сообщения, переданный в clientSocket.sendto(message,(serverName, serverPort)) на clientSocket.sendto(message.encode(),(serverName, serverPort)) . Тогда вы успешно запустились бы в python3

Ответ №5:

Всякий раз, когда вы сталкиваетесь с ошибкой с этим сообщением, используйте my_string.encode() .

(где my_string — строка, которую вы передаете функции / методу).

encode Метод str objects возвращает закодированную версию строки в виде bytes объекта, который затем можно использовать. В этом конкретном случае методы сокета, такие .send ожидают, что в качестве отправляемых данных будет отправлен объект bytes, а не объект string.

Поскольку у вас есть объект типа str , и вы передаете его функции / методу, который ожидает объект типа bytes , возникает ошибка, которая четко объясняет, что:

 TypeError: a bytes-like object is required, not 'str'
  

Поэтому необходим encode метод строк, применяемый к str значению и возвращающий bytes значение:

 >>> s = "Hello world"
>>> print(type(s))
<class 'str'>
>>> byte_s = s.encode()
>>> print(type(byte_s))
<class 'bytes'>
>>> print(byte_s)
b"Hello world"
  

Здесь префикс b в b'Hello world' обозначает, что это действительно объект bytes. Затем вы можете передать его любой ожидающей его функции, чтобы она работала плавно.

Ответ №6:

добавьте «b» в отправляемые данные следующим образом: request = client.send(b»GET / HTTP/1.1 r nHost: google.com r n r n»)