使用Python的select函数实现简单的聊天室程序。
发布时间:2023-12-24 04:12:33
聊天室是一个多人在线聊天的平台,参与者可以发送消息、接收消息并与其他用户互动。我们可以使用Python的select函数来实现一个简单的聊天室程序。
首先,我们需要导入select模块和socket模块,用于创建网络套接字和处理连接。然后,我们创建一个Server类来管理聊天室服务器。
import select
import socket
class Server:
def __init__(self, host, port):
self.host = host
self.port = port
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(5)
self.client_sockets = []
self.inputs = [self.server_socket]
def run(self):
print(f"Server is running on {self.host}:{self.port}...")
while True:
readable, _, _ = select.select(self.inputs, [], [])
for sock in readable:
if sock == self.server_socket:
client_socket, client_address = self.server_socket.accept()
self.client_sockets.append(client_socket)
self.inputs.append(client_socket)
print(f"New connection from {client_address}")
else:
try:
message = sock.recv(1024).decode()
if message:
self.broadcast(sock, message)
except:
self.remove_socket(sock)
def broadcast(self, sender_sock, message):
for client_socket in self.client_sockets:
if client_socket != self.server_socket and client_socket != sender_sock:
client_socket.send(message.encode())
def remove_socket(self, sock):
if sock in self.inputs:
self.inputs.remove(sock)
if sock in self.client_sockets:
self.client_sockets.remove(sock)
sock.close()
在Server类的__init__方法中,我们创建了一个TCP服务器套接字并绑定到指定的主机和端口。然后,我们使用select函数监听套接字的可读事件。当有新的连接到来时,我们接受该连接并将客户端套接字添加到inputs列表中,以便可以监听其可读事件。当有数据通过套接字发送过来时,我们使用recv方法接收并将消息广播给所有客户端套接字(除了发送者)。
接下来,我们创建一个Client类来连接到聊天室服务器并发送/接收消息。
import select
import socket
import sys
import threading
class Client:
def __init__(self, host, port):
self.host = host
self.port = port
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def connect(self):
try:
self.client_socket.connect((self.host, self.port))
print("Connected to the server.")
threading.Thread(target=self.receive).start()
while True:
message = input()
if message:
self.client_socket.send(message.encode())
except Exception as e:
print(f"Connection failed: {e}")
sys.exit()
def receive(self):
while True:
try:
readable, _, _ = select.select([self.client_socket], [], [])
if self.client_socket in readable:
message = self.client_socket.recv(1024).decode()
if not message:
print("Disconnected from the server.")
sys.exit()
else:
print(message)
except (KeyboardInterrupt, SystemExit):
sys.exit()
if __name__ == '__main__':
if len(sys.argv) != 3:
print("Usage: python chatroom.py <host> <port>")
sys.exit()
client = Client(sys.argv[1], int(sys.argv[2]))
client.connect()
在Client类的__init__方法中,我们创建一个TCP客户端套接字。在connect方法中,我们尝试连接到指定的主机和端口,并在成功连接后创建一个新线程来接收服务器发送的消息。然后,我们使用input函数从终端获取用户输入的消息,并使用send方法发送到服务器。在receive方法中,我们使用recv方法接收服务器发送的消息,并将其打印到终端。
运行聊天室程序的例子:
1. 启动服务器:
server = Server('localhost', 5000)
server.run()
2. 运行客户端(至少两个客户端):
client1 = Client('localhost', 5000)
client1.connect()
client2 = Client('localhost', 5000)
client2.connect()
3. 在客户端终端输入消息进行聊天。消息将被广播到其他客户端。
这是一个简单的基于select函数的聊天室程序示例。但请注意,此示例基于单线程,可能无法处理大量客户端连接和高并发情况。在实际应用中,您可能需要使用多线程或异步框架来处理更复杂的场景。
