2017-05-08 2 views
1

Ich versuche, einen Multithread-TCP-Server mit Python zu implementieren. Wenn ich den folgenden Code ausführen erhalte ich folgende Fehlermeldung:TCP-Multi-Thread-Server

Fehler

Incoming message: how are you 
Unhandled exception in thread started by <function client_thread at 0x00000000024499 E8> 
Traceback (most recent call last): 
File "tcp_test2.py", line 32, in client_thread 
message = recv_msg(conn) 
File "tcp_test2.py", line 24, in recv_msg 
raw_msglen = recvall(sock, 4) 
File "tcp_test2.py", line 13, in recvall 
raise EOFError('was expecting %d bytes but only received %d bytes before socket closed' % (length, len(data))) 
EOFError: was expecting 4 bytes but only received 0 bytes before socket closed 

nicht sicher, wo ich mit der Umsetzung der threading Funktion falsch werde. Jede Hilfe würde sehr geschätzt werden.

-Code

import argparse 
import socket 
import struct 
from thread import start_new_thread 

def recvall(sock, length): 
    data = b'' 
    while len(data) < length: 
     packet = sock.recv(length - len(data)) 
     if not packet: 
      raise EOFError('was expecting %d bytes but only received %d bytes before socket closed' % (length, len(data))) 
     data += packet 
    return data 

def send_msg(sock, msg): 
    msg = struct.pack('>I', len(msg)) + msg 
    sock.sendall(msg) 


def recv_msg(sock): 
    raw_msglen = recvall(sock, 4) 
    if not raw_msglen: 
     return None 
    msglen = struct.unpack('>I', raw_msglen)[0] 
    return recvall(sock, msglen) 

def client_thread(conn): 
    while True: 
     message = recv_msg(conn) 
     print('Incoming message: {}'.format(message)) 
     conn.sendall(b'Message Received') #send data to the socket 
    conn.close() #mark the socket closed 
    print('\tReply sent, socket closed') 

Server

def server(interface, port): 

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    sock.bind((interface, port)) # the socket to address 
    sock.listen(1) #listen for connections made to the socket. 
    while True: 
     conn, sockname = sock.accept() 
     start_new_thread(client_thread,(conn,)) 

    sock.close() 

Kunde

def client(host, port): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.connect((host, port)) 
    print('Client has been assigned socket name', sock.getsockname()) 
    message = raw_input("Type your message: ") 
    send_msg(sock, message) 
    reply = recvall(sock, 16) 
    print('Server Response: {}'.format(reply)) 
    print('\nSocket closed') 
    sock.close() 

if __name__ == '__main__': 
    choices = {'client': client, 'server': server} 
    parser = argparse.ArgumentParser(description='Send and receive over TCP') 
    parser.add_argument('role', choices=choices, help='which role to play') 
    parser.add_argument('host', help='interface the sever listens at:' 'host the client sends to') 
    parser.add_argument('-p', metavar='PORT', type=int, default=1060, help='TCP port(default 1060)') 
    args = parser.parse_args() 
    function = choices[args.role] 
    function(args.host, args.p) 

Dies ist mein vorheriger Code, der keine unbehandelten Ausnahmen hat

import argparse 
import socket 
import struct 

def recvall(sock, length): 
    data = b'' 
    while len(data) < length: 
     packet = sock.recv(length - len(data)) 
     if not packet: 
      raise EOFError('was expecting %d bytes but only received %d bytes before socket closed' % (length, len(data))) 
     data += packet 
    return data 

def send_msg(sock, msg): 
    msg = struct.pack('>I', len(msg)) + msg 
    sock.sendall(msg) 


def recv_msg(sock): 
    raw_msglen = recvall(sock, 4) 
    if not raw_msglen: 
     return None 
    msglen = struct.unpack('>I', raw_msglen)[0] 
    return recvall(sock, msglen) 


def server(interface, port): 

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    sock.bind((interface, port)) # the socket to address 
    sock.listen(1) #listen for connections made to the socket. 
    print('Listening at {}'.format(sock.getsockname())) #returns the socket's own address 
    while True: 
     conn, sockname = sock.accept() 
     print('Connection accepted from {}'.format(sockname)) 
     print('\tServer Socket: {}'.format(conn.getsockname())) 
     print('\tClient Socket: {}'.format(conn.getpeername())) # return remote address to which socket is connected 
     message = recv_msg(conn) 
     print('Incoming message: {}'.format(message)) 
     conn.sendall(b'Message Received') #send data to the socket 
     conn.close() #mark the socket closed 
     print('\tReply sent, socket closed') 

def client(host, port): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.connect((host, port)) 
    print('Client has been assigned socket name', sock.getsockname()) 
    message = raw_input("Type your message: ") 
    send_msg(sock, message) 
    reply = recvall(sock, 16) 
    print('Server Response: {}'.format(reply)) 
    print('\nSocket closed') 
    sock.close() 


if __name__ == '__main__': 
    choices = {'client': client, 'server': server} 
    parser = argparse.ArgumentParser(description='Send and receive over TCP') 
    parser.add_argument('role', choices=choices, help='which role to play') 
    parser.add_argument('host', help='interface the sever listens at:' 'host the client sends to') 
    parser.add_argument('-p', metavar='PORT', type=int, default=1060, help='TCP port(default 1060)') 
    args = parser.parse_args() 
    function = choices[args.role] 
    function(args.host, args.p) 
+0

Ich könnte eine bessere Antwort geben, wenn Sie erklären, was Sie erwartet haben. Das Verhalten, das Sie haben, ist genau das, was Sie erwartet haben sollten. –

Antwort

1

Nichts ist falsch. Ihr Client schließt den Socket. Der Server erkennt dies, wenn er versucht, die nächste Nachricht zu lesen. Das hätte genau das sein sollen, was Sie erwartet haben.

+0

Danke für den Kommentar David. Ich verstehe einfach nicht, warum ich eine unbehandelte Ausnahme mit diesem Code bekomme. Ohne die Threading-Funktion bekomme ich diese nicht behandelte Ausnahme nicht. Ich bekomme nur die wünschenswerte Nachricht, die der Kunde gesendet hat. Ich möchte in der Lage sein, die Ausgabe zu reinigen, die auf dem Server angezeigt wird. –

+0

Verstehst du, dass dein Code einen EOFError beim normalen Schließen auslöst? –

+0

Ja Ich verstehe, dass EOFError ausgelöst wird, wenn keine Bytes mehr gesendet werden. Könntest du mir bitte erklären, warum es dann eine unbehandelte Ausnahme ist? Ich habe meinen vorherigen Code gepostet, der keine unbehandelte Ausnahme zum Vergleich hatte. –