首页 > 解决方案 > python套接字服务器中的客户端线程

问题描述

我在 Python 套接字上制作了一个控制台聊天应用程序。我想在客户端实现线程,以便有一个线程用于接收消息和一个线程用于发送消息。我不太确定如何在 python 中实现线程。有人可以帮忙或给我一些建议。

这是我在客户端的代码:

import socket
import select
import errno
import sys, struct
import pickle

HEADER_LENGTH = 1024
IP = "127.0.0.1"
PORT = 9669
def pad(package):
    return package + [0]*(HEADER_LENGTH-len(package))

def send_login_request(username):
    type_pac = 1
    package_type = type_pac.to_bytes(1,'big')
    print(package_type)
    length = len(username)
    if length > 1019:
        print ("Error: Username too long")
        sys.exit()
    package = package_type + struct.pack("I", length) + username.encode()
    # package = pad(package)
    
    return package

def send_message(recv_id, message):
    type_pac = 2
    package_type = type_pac.to_bytes(1,"big")
    recv_id = recv_id.to_bytes(1,'big')
    length = len(message)
    if length > 1015:
        print('message too long')
        sys.exit()
    package = package_type + recv_id + struct.pack('I', length) + message.encode()
   
    return package



client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect to a given ip and port
client_socket.connect((IP, PORT))

my_username = input("Username: ")
request = send_login_request(my_username)   
print(request)
client_socket.send(request)
username_conf = client_socket.recv(1024).decode()
print(username_conf)
if username_conf == "Welcome to the server":


    recv_id = int(input("Please enter receiver's id"))

    while True:
            # Wait for user to input a message

            message = input(f'{my_username} > ')
            # If message is not empty - send it
            if message:

                send_message = send_message(recv_id,message)
                client_socket.send(send_message)

            try:

                    message_receiver = client_socket.recv(HEADER_LENGTH).decode()
                    
                    # Print message
                    print(f'> {message_receiver}')

            except IOError as e:

                if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
                    print('Reading error: {}'.format(str(e)))
                    sys.exit()

                # We just did not receive anything
                continue

            except Exception as e:
                # Any other exception - something happened, exit
                print('Reading error: {}'.format(str(e)))
                sys.exit()

谢谢!

标签: pythonmultithreadingsocketstcp

解决方案


看看这部分代码:

while True:
    #[...]
    try:
        message_receiver = client_socket.recv(HEADER_LENGTH).decode()
        # Print message
        print(f'> {message_receiver}')
    except:
        #[...]

您需要为此try-except块创建函数并在线程中调用它。

from threading import Thread
def recv():
    try:
        message_receiver = client_socket.recv(HEADER_LENGTH).decode()
        # Print message
        print(f'> {message_receiver}')
    except:
        #[...]


while True:
    #[...]
    recv_thread = Thread(target=recv)
    recv_thread.start()

所以你的最终代码应该是这样的:

import socket
import select
import errno
import sys, struct
import pickle

HEADER_LENGTH = 1024
IP = "127.0.0.1"
PORT = 9669
def pad(package):
    return package + [0]*(HEADER_LENGTH-len(package))

def send_login_request(username):
    type_pac = 1
    package_type = type_pac.to_bytes(1,'big')
    print(package_type)
    length = len(username)
    if length > 1019:
        print ("Error: Username too long")
        sys.exit()
    package = package_type + struct.pack("I", length) + username.encode()
    # package = pad(package)
    
    return package

def recv():
    try:
        message_receiver = client_socket.recv(HEADER_LENGTH).decode()
        # Print message
        print(f'> {message_receiver}')

    except:
        if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
            print('Reading error: {}'.format(str(e)))
            sys.exit()

        # We just did not receive anything
        continue

        except Exception as e:
            # Any other exception - something happened, exit
            print('Reading error: {}'.format(str(e)))
            sys.exit()

def send_message(recv_id, message):
    type_pac = 2
    package_type = type_pac.to_bytes(1,"big")
    recv_id = recv_id.to_bytes(1,'big')
    length = len(message)
    if length > 1015:
        print('message too long')
        sys.exit()
    package = package_type + recv_id + struct.pack('I', length) + message.encode()
   
    return package



client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect to a given ip and port
client_socket.connect((IP, PORT))

my_username = input("Username: ")
request = send_login_request(my_username)   
print(request)
client_socket.send(request)
username_conf = client_socket.recv(1024).decode()
print(username_conf)
if username_conf == "Welcome to the server":


    recv_id = int(input("Please enter receiver's id"))

    while True:
        # Wait for user to input a message

        message = input(f'{my_username} > ')
        # If message is not empty - send it
        if message:

            send_message = send_message(recv_id,message)
            client_socket.send(send_message)
            recv_thread = Thread(target=recv)
            recv_thread.start()            

推荐阅读