Python 编写多个 TCP Client一起聊天程序
目录
Python 编写多个 TCP Client一起聊天程序
查询电脑IP地址
建立TCP Client端
建立TCP Server端
建立通信
查询电脑IP地址
首先可以通过进入命令窗口之后,输入:ipconfig ,按下回车即可看到着整个电脑的ip详细信息,这里可以看到IPv4 地址为: 10.88.34.234
或者也可以通过网络与共享中心中的已链接的网络,看到网络的详细IP配置信息。
TCP通信需要经过创建连接、数据传送、终止连接三个步骤。在通信开始之前,一定要先建立相关的链接,才能发送数据
建立TCP Client端
下面为简单的TCP客户端,用于连接到指定的服务器地址和端口,发送一条消息,然后关闭连接。客户端是单次交互的,即它发送一条消息后就关闭了连接。想要使其成为一个完整的聊天客户端,它需要能够持续接收和发送消息,直到用户决定退出。
-
import socket # 1.创建socket tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2. 链接服务器 server_addr = ("10.88.34.234", 7002) tcp_socket.connect(server_addr) # 3. 发送数据 send_data = input("请输入要发送的数据:") tcp_socket.send(send_data.encode("gbk")) # 4. 关闭套接字 tcp_socket.close()
根据提供的代码进行改进,可以持续发送和接收消息,直到用户输入特定的命令(例如"exit")来关闭连接,同时,在多线程环境中,确保线程安全性是非常重要的,特别是涉及到共享资源(如 socket)时。当多个线程同时试图发送消息,可能导致发送的数据混乱,或者产生异常。
使用锁(threading.Lock)来保护共享资源,确保在某一时刻只有一个线程能够访问这个资源。在代码中添加一个锁,以确保在发送消息时不会被其他线程中断:
-
import socket import threading # 添加一个锁 send_lock = threading.Lock() def receive_messages(client_socket): try: while True: data = client_socket.recv(1024) if not data: break print(data.decode('gbk')) except Exception as e: print(f"Error receiving messages: {e}") def send_message(tcp_socket, message): # 使用锁确保发送操作的原子性 with send_lock: tcp_socket.send(message.encode('gbk')) def start_client(server_addr): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as tcp_socket: tcp_socket.connect(server_addr) # 启动接收消息的线程 receive_thread = threading.Thread(target=receive_messages, args=(tcp_socket,)) receive_thread.start() while True: send_data = input("请输入要发送的数据:") if send_data.lower() == "exit": break # 调用发送消息的函数 send_message(tcp_socket, send_data) receive_thread.join() if __name__ == "__main__": server_addr = ("10.88.34.234", 7002) start_client(server_addr)
建立TCP Server端
在程序中,如果想要完成一个TCP服务器的功能,需要以下流程:1. socket创建一个套接字;2. bind绑定ip和port;3. listen使套接字变为可以被动链接;4. accept等待客户端的链接,5. recv接收数据
基本的TCP服务器,它可以监听指定的IP地址和端口,接受客户端的连接请求,并接收来自客户端的数据。
-
import socket # 创建socket tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 本地信息 address = ('10.88.34.234', 7002) # 绑定 tcp_server_socket.bind(address) tcp_server_socket.listen(128) while True: # 等待新的客户端连接 client_socket, clientAddr = tcp_server_socket.accept() # 接收对方发送过来的数据 recv_data = client_socket.recv(1024) # 接收1024个字节 print('接收到的数据为:', recv_data.decode('gbk')) client_socket.close() tcp_server_socket.close()
修改后的代码可以支持多客户端,并且使客户端之间可以互相通讯:使用多线程处理每个客户端连接。保存所有活跃的客户端连接,以便可以将消息转发给所有客户端。
可以处理多个客户端的连接,并将任何客户端发送的消息转发给所有其他客户端。当客户端断开连接时,服务器将从列表中移除该客户端,并关闭相应的socket。当服务器接收到来自客户端的消息时,它会在消息前添加发送者的地址信息,然后将这个消息转发给所有其他客户端。
-
import socket import threading def handle_client(client_socket, client_addr, all_clients): while True: try: # 接收数据 recv_data = client_socket.recv(1024) print(f"接收到来自 {client_addr} 的数据: {recv_data.decode('gbk')}") if recv_data: # 构建带有发送者地址的消息 message = f"接收到来自 {client_addr} 的数据: {recv_data.decode('gbk')}" # 转发数据给所有客户端 broadcast(message.encode('gbk'), client_socket, all_clients) else: # 如果接收的数据为空,则表示客户端已经断开 remove_client(client_socket, all_clients) break except ConnectionResetError: # 处理客户端异常断开的情况 remove_client(client_socket, all_clients) break def broadcast(message, sender_socket, all_clients): for client in all_clients: if client is not sender_socket: try: client.send(message) except Exception as e: print(f"Error sending message to client: {e}") def remove_client(client_socket, all_clients): client_socket.close() all_clients.remove(client_socket) print(f"Removed client: {client_socket}") def start_server(): server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('10.88.34.234', 7002)) server_socket.listen(128) all_clients = [] while True: client_socket, client_addr = server_socket.accept() print(f"Accepted connection from {client_addr}") all_clients.append(client_socket) client_thread = threading.Thread(target=handle_client, args=(client_socket, client_addr, all_clients)) client_thread.start() if __name__ == "__main__": start_server()
建立通信
打开四个进程,第一个进程用于运行TCP Server程序,其余三个作为不同的三个TCP Client端。分别运行并建立连接并通信。
当Client1发送消息时
服务器和其他两个Client均接收到消息
client在接收到其他client发送过来的消息后,也可以再次发送消息,直至发送exit后退出
当客户端断开连接时,服务器将从列表中移除该客户端,并关闭相应的socket。文章来源:https://www.toymoban.com/news/detail-858439.html
文章来源地址https://www.toymoban.com/news/detail-858439.html
到了这里,关于Python 编写多个 TCP Client一起聊天程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!