我在 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()
谢谢!
答案 0 :(得分:0)
看看这部分代码:
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()