web-dev-qa-db-fra.com

Python erreur de socket TypeError: un objet de type octet est requis, pas "str" ​​avec la fonction d'envoi

J'essaie de créer un programme qui ouvrira un port sur la machine locale et permettra aux autres utilisateurs de s'y connecter via netcat. Mon code actuel est.

s = socket.socket()
Host = '127.0.0.1'
port = 12345
s.bind((Host, port))

s.listen(5)
while True:
    c, addr = s.accept()
    print('Got connection from', addr)
    c.send('Thank you for connecting')
    c.close()

Je suis nouveau sur Python et sur les sockets. Mais lorsque je lance ce code, il me permet d’envoyer une connexion netcat avec la commande suivante:

nc 127.0.0.1 12345

Mais ensuite, sur mon script Python, le message d'erreur correspondant à c.send s'affiche:

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

En fait, j'essaye simplement d'ouvrir un port, de permettre à Netcat de se connecter et d'avoir un shell complet sur cette machine.

20
sqlsqlsql

La raison de cette erreur est que, dans Python 3, les chaînes sont au format Unicode, mais lors de la transmission sur le réseau, les données doivent plutôt être des chaînes d'octets. Alors ... quelques suggestions:

  1. Suggérez d’utiliser c.sendall() au lieu de c.send() pour éviter d’éventuels problèmes dans lesquels vous n’auriez peut-être pas envoyé le message en entier avec un seul appel (voir documents ).
  2. Pour les littéraux, ajoutez un 'b' pour la chaîne d'octets: c.sendall(b'Thank you for connecting')
  3. Pour les variables, vous devez encoder des chaînes Unicode en chaînes d'octets (voir ci-dessous).

Meilleure solution (devrait fonctionner avec les deux versions 2.x et 3.x):

output = 'Thank you for connecting'
c.sendall(output.encode('utf-8'))

Épilogue/arrière-plan : ce n'est pas un problème dans Python 2 parce que les chaînes sont déjà des chaînes d'octets - votre code OP fonctionnerait parfaitement dans cet environnement. Les chaînes Unicode ont été ajoutées à Python dans les versions 1.6 et 2.0, mais ont été reléguées au second plan jusqu'à ce qu'elles deviennent le type de chaîne par défaut. Voir aussi cette question similaire ainsi que celui-ci .

39
wescpy

Vous pouvez le décoder en str avec receive.decode('utf_8').

7
Eren Arıcı

Vous pouvez changer la ligne d'envoi en ceci:

c.send(b'Thank you for connecting')

Le b le rend octets à la place.

5
sjjhsjjh