2017-05-08 168 views
1

我正在尝试使用Python实现多线程TCP服务器。当我运行下面的代码我得到了以下错误:TCP多线程服务器

错误

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 

不知道我在哪里与执行线程功能走错了。任何帮助将不胜感激。

代码

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') 

服务器

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() 

客户

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) 

这是我以前的代码没有任何未处理的异常

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

如果你解释你期望发生的事情,我可以提供更好的答案。你得到的行为正是你应该预料到的。 –

回答

1

没有错。您的客户端关闭套接字。服务器在尝试读取下一条消息时检测到此情况。这应该是你所期望的。

+0

感谢您的评论大卫。我只是不明白为什么我得到这个代码未处理的异常。没有线程函数,我不会得到这个未处理的异常。我只得到客户发送的理想讯息。我希望能够清除在服务器上显示的输出。 –

+0

你知道你的代码在正常关闭时会引发EOFError吗? –

+0

是的我明白,没有更多的字节发送时会引发EOFError。但是,请你向我解释为什么然后它认为它是一个未处理的异常? 我发布了我以前的代码,没有任何未处理的异常进行比较。 –