2017-02-26 23 views
1

Ich mache eine einfache Python-Anwendung, die Menschen über eine CLI miteinander kommunizieren können. Ich bin relativ neu auf dem Sockets-Modul, aber mein Code hat keine Probleme. Außer einem. Wenn ich meine zwei Skripts (chatclient.py und chatserver.py) ausführe, laufen sie gut. Der Server wird gestartet, und der Client fragt den Benutzer nach seinem Namen und der Nachricht. Doch nach dem Klicken Sie hier die Nachricht zu senden, i erhalten:Python3 Socket-Modul: Entschlüsselung str

TypeError: decoding str not supported 

Ich habe .encode ('utf-8)/.decode (' utf-8'), aber immer noch die gleichen Fehler versucht, mit. Der Code wird unten sein (mit mehreren Kommentaren um den "falschen" Code).

#client.py 
import socket 
import threading 
import time 

tLock = threading.Lock() #creates a lock for the thread and prevents output to the screen 
shutdown = False 

def receiving(name, sock): 
    while not shutdown: #while the program is still running 
     try: 
      tLock.acquire() #acquires the lock 
      while True: 
       data, addr = sock.recv(1024).decode('utf-8') #gets the data and address from the data received 
       print(str(data)) 
     except: 
      pass 

     finally: 
      tLock.release() #releases the lock 

host = "127.0.0.1" #uses localhost as the host 
port = 0 #picks up any free port on the computer 

server = ("127.0.0.1",5000) 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind((host, port)) 
s.setblocking(0) 

rt = threading.Thread(target=receiving, args=("RecvThread", s)) 
rt.start() 

'''name = input("Enter your name: ") 
message = input("> ") 
while message != "q": 
    if message != '': 
     print("From ",name) 
     s.sendto(str(name, message), (host,port)).decode('utf-8')''' 

    tLock.acquire() 
    message = input('') 
    tLock.release() 
    time.sleep(0.5) 

shutdown = True 
rt.join() 
s.close() 

^^^ Client

#server.py 
import socket 
import time 

host = "127.0.0.1" #makes localhost the host server 
port = 5000   #uses any random port between 1024 and 65535 

clients = [] 

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #creates a new socket object 
s.bind((host,port)) #binds the host and port to socket object 
s.setblocking(0)  #sets the blocking to 0 (essentially no blocking) 

quitting = False 
print("The server has now started on ",time.ctime(time.time())) 

while not quitting: #while quitting hasn't happened 
    try: 
     data, addr = s.recvfrom(1024).decode('utf-8') #tries to get data and address from the data coming in 
     if "Quit" in data: #if the data has quit in it 
      quitting = True #quitting = true meaning the while not quitting loop would break 
     if addr not in clients: #if the address given is not in the list 'Clients' 
      clients.append(addr) #then it will append it to the list 

     print(time.ctime(time.time()),"- ",str(addr).decode('utf-8')," : ",str(data).decode('utf-8')) #prints the time, the address and the message 

     for client in clients: #for each client in the list of clients 
      s.sendto(bytes(data, 'utf-8')) #send the data to the clients 
      s.sendto(bytes(client, 'utf-8')) 

    except: 
     pass 

s.close() 

^^^ Server

+0

Es gibt keine 'decode' Methode für Strings in Python 3 als Strings Strings jetzt Unicode sind. Sie können das Byte-Objekt decodieren (z. B. das Ergebnis von 'bytes (blah)' oder 'blah" .encode() '). – avysk

Antwort

1

Wenn Sie passieren 2 oder mehr Werte zu str, versucht, sie zu entschlüsseln, aber in Ihrem Fall das erste Argument bereits String-Objekt (weil der Rückgabewert von input Funktion String ist); verursacht den Fehler.

>>> str('a') 
'a' 
>>> str('a', 'utf-8') # trying to decode (the 2nd arg. is encoding) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: decoding str is not supported 
>>> str(b'a', 'utf-8') 
'a' 

Daneben müssen Sie Byte Objekt socket.sendto als erstes Argument übergeben. Encode-String ein Byte-Objekt zu erhalten:

>>> 'a'.encode() # You can omit encoding arg.; `utf-8` is default in Python 3.x 
b'a' 
>>> 'a'.encode('utf-8') 
b'a' 

folgende Zeile von Client-Code ersetzen:

s.sendto(str(name, message), (host,port)).decode('utf-8') 

mit:

s.sendto('{}: {}'.format(name, message).encode('utf-8'), (host,port)) 

data, addr = s.recvfrom(1024).decode('utf-8') 

Oberhalb der Zeile ist auch falsch. socket.recvfrom(..) gibt ein Tupel von (Nachricht, Adresse) zurück. Die tuple hat keine decode Methode. Sie müssen nur message dekodieren.

data, addr = s.recvfrom(1024) 
data = data.decode('utf-8') 

Server

import socket 
import time 

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
s.bind(('127.0.0.1', 5000)) 

print("The server has now started on ", time.ctime()) 

clients = [] 
while True: 
    data, addr = s.recvfrom(1024) 
    text = data.decode('utf-8') 
    if "Quit" in text: 
     break 

    if addr not in clients: 
     clients.append(addr) 

    print(time.ctime(), "-", addr, ":", text) 
    for client in clients: 
     s.sendto(data, client) 

s.close() 
+0

Der Fehler ist verschwunden, aber ich erhalte keine Nachrichten. Ich habe zu Terminal-Tabs geöffnet, auf denen der Code läuft, aber sobald ich meinen Namen und meine Nachricht eingebe, sagt der Client nur 'from name:' ​​und sonst nichts? Würdest du zufällig wissen warum? –

+0

@ELiTEMAGiK, Servercode hat einen großen 'try: ... except: pass' Block. Es wird alle Ausnahmen überschatten. Versuchen Sie, es zu entfernen, und führen Sie es aus. Sie werden sehen, was das Problem ist. Hinweis: Nicht alle Ausnahmen abfangen, sondern eine bestimmte; und behandeln Sie die Ausnahme. Nur "Pass" ist keine gute Übung. – falsetru

+0

@ELiTEMagiK, Ein weiteres Problem: Der Client sendet an '(Host, Port)' wobei 'Port = 0' ist. Sie sollten die von Ihnen definierte 'server' -Variable anstelle von' (host, port) 'verwenden, die zum Binden des Client-Sockets verwendet wird. Übrigens müssen Sie den Client-Socket nicht binden. – falsetru

Verwandte Themen