TCP多线程服务器

时间:2017-05-08 16:09:40

标签: python multithreading sockets

我正在尝试使用Python实现多线程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)

1 个答案:

答案 0 :(得分:1)

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