python socket 实时通信,多对多,一对一,转发

研究一下python socket 实时通信,多对多,一对一,转发

C=>S 单独通信

server1

import socket
import threading# 在线客户端列表
online_clients = {}def broadcast(message, sender):"""向所有在线客户端广播消息,除了发送者"""for client_socket, addr in online_clients.items():if client_socket != sender:try:client_socket.send(message)except:# 客户端离线,从列表中移除online_clients.pop(client_socket)def handle_client(client_socket, addr):"""处理单个客户端的通信"""while True:try:data = client_socket.recv(1024)if not data:breakprint(f"从 {addr} 收到消息: {data.decode()}")broadcast(data, client_socket)except:break# 客户端离线,从列表中移除online_clients.pop(client_socket)client_socket.close()print(f"客户端 {addr} 已离线")# 启动服务器
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("localhost", 8000))
server_socket.listen(5)
print("服务器已启动,等待客户端连接...")while True:client_socket, addr = server_socket.accept()print(f"新客户端 {addr} 已连接")online_clients[client_socket] = addrthreading.Thread(target=handle_client, args=(client_socket, addr)).start()

client1

import socket# 创建 Socket 对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 连接服务器
server_address = ("localhost", 8000)
client_socket.connect(server_address)while True:message = input("输入消息: ")client_socket.sendall(message.encode())# 接收服务器响应data = client_socket.recv(1024)print(f"接收服务器响应收到消息: {data.decode()}")client_socket.close()

效果:
在这里插入图片描述

C<=>S 相互通信

server2

import socket
import select# 在线客户端列表
online_clients = {}def broadcast(message, sender):"""向所有在线客户端广播消息,除了发送者"""for client_socket, addr in online_clients.items():if client_socket != sender:try:client_socket.sendall(message)except:# 客户端离线,从列表中移除online_clients.pop(client_socket)def server_loop():server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_socket.bind(("localhost", 8000))server_socket.listen(5)print("服务器已启动,等待客户端连接...")# 使用 select 监听 socket 列表inputs = [server_socket]while True:# 阻塞等待至少一个socket准备好进行I/O操作readable, writeable, exceptional = select.select(inputs, [], [])for sock in readable:if sock is server_socket:# 新的连接请求client_socket, addr = server_socket.accept()print(f"新客户端 {addr} 已连接")online_clients[client_socket] = addrinputs.append(client_socket)else:# 已连接客户端发来消息try:data = sock.recv(1024)if data:message = f"客户端 {online_clients[sock]}: {data.decode()}"print(message)broadcast(message.encode(), sock)else:# 客户端离线,从列表中移除online_clients.pop(sock)inputs.remove(sock)sock.close()print(f"客户端 {online_clients[sock]} 已离线")except:# 客户端异常,从列表中移除online_clients.pop(sock)inputs.remove(sock)sock.close()print(f"客户端 {online_clients[sock]} 已离线")if __name__ == "__main__":server_loop()

client2

import socket
import threadingdef send_message(client_socket):while True:message = input()client_socket.sendall(message.encode())def receive_message(client_socket):while True:try:data = client_socket.recv(1024)if data:print(data.decode())else:# 服务器断开连接breakexcept:breakif __name__ == "__main__":client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_address = ("localhost", 8000)client_socket.connect(server_address)print("已连接到服务器")threading.Thread(target=send_message, args=(client_socket,)).start()threading.Thread(target=receive_message, args=(client_socket,)).start()

效果:
在这里插入图片描述

C<->S 固定端口一一对应

server3

import socket
import select
from collections import defaultdict# 客户端端口号映射
client_ports = {50106: "A",50107: "B",50108: "C"
}# 允许通信的端口号对
allowed_ports = {50106: [50108],50107: [50109],50108: [50106]
}# 在线客户端列表,{端口号: socket}
online_clients = {}
# 消息队列,{端口号: [(发送者端口号, 消息)]}
message_queues = defaultdict(list)def send_message(sender_port, target_port, message):"""向指定端口号的客户端发送消息"""target_socket = online_clients.get(target_port)if target_socket:try:target_socket.sendall(f"{sender_port}: {message}".encode())except:# 接收方离线,将消息加入队列message_queues[target_port].append((sender_port, message))else:# 目标端口号不存在,将消息加入队列message_queues[target_port].append((sender_port, message))def server_loop():server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_socket.bind(("localhost", 8000))server_socket.listen(5)print("服务器已启动,等待客户端连接...")# 使用 select 监听 socket 列表inputs = [server_socket]while True:# 阻塞等待至少一个socket准备好进行I/O操作readable, writeable, exceptional = select.select(inputs, [], [])for sock in readable:if sock is server_socket: # 新的连接请求client_socket, addr = server_socket.accept()print(f"新客户端 {addr} 已连接")# client_port = client_socket.getsockname()[1]client_port = addr[1] online_clients[client_port] = client_socketinputs.append(client_socket)# 将离线期间的消息队列发送给新上线客户端for sender_port, message in message_queues.pop(client_port, []):client_socket.sendall(f"{sender_port}: {message}".encode())else:# 已连接客户端发来消息try:data = sock.recv(1024)if data:print(f"接收到消息: {data} ")# 解析消息,格式为 "目标端口号:消息内容"parts = data.decode().split(':')  # 确保拆分后的部分数量正确  if len(parts) == 3:  # 转换第一个部分为整数,作为sender_port  sender_port = int(parts[0])# 转换第二个部分为整数,作为target_port    target_port = int(parts[1])  # 第三个部分作为messagemessage = parts[2]          # 检查是否允许通信if target_port in allowed_ports.get(sender_port, []):send_message(sender_port, target_port, message)else:print(f"客户端 {client_ports.get(sender_port, sender_port)} 试图与未授权端口 {target_port} 通信")else:# 客户端离线,从列表中移除client_port = sock.getsockname()[1]online_clients.pop(client_port)inputs.remove(sock)sock.close()print(f"客户端 {client_ports.get(client_port, client_port)} 已离线")except: try:  # 获取远程客户端的地址和端口号  client_address, client_port = sock.getpeername()  print(f"客户端 {client_address}:{client_port} 报错离线离线")# 根据需要处理client_port,例如从列表中移除  online_clients.pop(client_port, None)  # 使用pop的第二个参数避免KeyError  inputs.remove(sock)  sock.close()  print(f"客户端 {client_address}:{client_port} 已离线")except Exception as e:  # 处理可能出现的异常,例如socket已经关闭等  print(f"客户端强制离线Error handling client socket: {e}") if __name__ == "__main__":server_loop()

client3-1

import socket
import threadingdef send_message(client_socket,sender_port, target_port):while True:message = input()if message.strip() == "exit":breakclient_socket.sendall(f"{sender_port}:{target_port}:{message}".encode())def receive_message(client_socket):while True:try:data = client_socket.recv(1024)if data:print(data.decode())else:# 服务器断开连接breakexcept:breakif __name__ == "__main__":client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_address = ("localhost", 8000)sender_port = 50106client_socket.bind(("localhost", sender_port))  # 绑定固定端口号 50108client_socket.connect(server_address)client_port = client_socket.getsockname()[1]print(f"已连接到服务器,本地端口号为 {client_port}")# 客户端 A  只能与端口号 50106 的客户端  C通信target_port = 50108sender_thread = threading.Thread(target=send_message, args=(client_socket, sender_port,target_port))receiver_thread = threading.Thread(target=receive_message, args=(client_socket,))sender_thread.start()receiver_thread.start()sender_thread.join()client_socket.close()

client3-2

import socket
import threadingdef send_message(client_socket,sender_port, target_port):while True:message = input()if message.strip() == "exit":breakclient_socket.sendall(f"{sender_port}:{target_port}:{message}".encode())def receive_message(client_socket):while True:try:data = client_socket.recv(1024)if data:print(data.decode())else:# 服务器断开连接breakexcept:breakif __name__ == "__main__":client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_address = ("localhost", 8000)sender_port = 50107client_socket.bind(("localhost", sender_port))  # 绑定固定端口号 50108client_socket.connect(server_address)client_port = client_socket.getsockname()[1]print(f"已连接到服务器,本地端口号为 {client_port}")# 客户端 A  只能与端口号 50106 的客户端  C通信target_port = 50109sender_thread = threading.Thread(target=send_message, args=(client_socket, sender_port,target_port))receiver_thread = threading.Thread(target=receive_message, args=(client_socket,))sender_thread.start()receiver_thread.start()sender_thread.join()client_socket.close()

client3-3

import socket
import threadingdef send_message(client_socket,sender_port, target_port):while True:message = input()if message.strip() == "exit":breakclient_socket.sendall(f"{sender_port}:{target_port}:{message}".encode())def receive_message(client_socket):while True:try:data = client_socket.recv(1024)if data:print(data.decode())else:# 服务器断开连接breakexcept:breakif __name__ == "__main__":client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_address = ("localhost", 8000)sender_port = 50108client_socket.bind(("localhost", sender_port))  # 绑定固定端口号 50108client_socket.connect(server_address)client_port = client_socket.getsockname()[1]print(f"已连接到服务器,本地端口号为 {client_port}")# 客户端 C 只能与端口号 50106 的客户端 A 通信target_port = 50106sender_thread = threading.Thread(target=send_message, args=(client_socket, sender_port,target_port))receiver_thread = threading.Thread(target=receive_message, args=(client_socket,))sender_thread.start()receiver_thread.start()sender_thread.join()client_socket.close()

C<-S-S->C 固定端口一一对应

local

import socket
import threading# TCP服务器地址和端口
SERVER1_ADDRESS = ('localhost', 8001)
SERVER2_ADDRESS = ('localhost', 8002)# 用于从一个socket接收数据并发送到另一个socket的函数
def forward_data(source_socket, dest_socket):while True:try:data = source_socket.recv(1024)if data:dest_socket.sendall(data)except:break# 连接到8001端口的函数
def connect_to_server1():while True:try:server1_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server1_socket.connect(SERVER1_ADDRESS)print("已连接到8001端口")return server1_socketexcept:print("连接8001端口失败,正在重试...")continue# 连接到8002端口的函数
def connect_to_server2():while True:try:server2_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server2_socket.connect(SERVER2_ADDRESS)print("已连接到8002端口")return server2_socketexcept:print("连接8002端口失败,正在重试...")continue# 连接到8001端口
server1_socket = connect_to_server1()# 连接到8002端口
server2_socket = connect_to_server2()# 创建两个线程,分别用于数据转发
thread1 = threading.Thread(target=forward_data, args=(server1_socket, server2_socket))
thread2 = threading.Thread(target=forward_data, args=(server2_socket, server1_socket))# 启动线程
thread1.start()
thread2.start()# 等待线程结束
thread1.join()
thread2.join()

server

import socket
import threading
from collections import defaultdict# 存储每个端口连接的客户端,使用defaultdict初始化为列表
clients = defaultdict(list)def handle_client(client_socket, client_address, port):while True:try:data = client_socket.recv(1024)if data:# 将数据转发给另一个端口的所有客户端other_port = 8000 if port == 8001 else 8001for other_client in clients[other_port]:other_client.send(data)else:# 如果没有数据,关闭连接breakexcept Exception as e:print(f"Error handling data from {client_address}: {e}")breaktry:# 从客户端列表中移除断开连接的客户端clients[port].remove(client_socket)client_socket.close()print(f"Closed connection to {client_address}")except Exception as e:print(f"Closed connection to  {client_address}:{port} => {e}")def accept_connections(port):with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(('', port))server_socket.listen()print(f"Listening on port {port}")while True:try:client_socket, client_address = server_socket.accept()print(f"Accepted connection from {client_address} on port {port}")clients[port].append(client_socket)# 创建一个新线程来处理客户端threading.Thread(target=handle_client, args=(client_socket, client_address, port)).start()except RuntimeError as e:print(f"创建一个新线程来处理客户端 {port} => {e}")# 创建并启动两个线程,分别监听8000和8001端口
thread1 = threading.Thread(target=accept_connections, args=(8000,))
thread2 = threading.Thread(target=accept_connections, args=(8001,)) thread1.start()
thread2.start()thread1.join()
thread2.join()

local_server

import socket
import threading# 创建一个TCP/IP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 绑定IP地址和端口
server_address = ('', 8002)
server_socket.bind(server_address)# 开始监听连接
server_socket.listen(5)
print("等待连接[8002]...")# 客户端列表
clients = []# 处理客户端连接的函数def handle_client(client_socket, address):print(f"已连接 {address}")clients.append(client_socket)while True:try:# 接收客户端消息data = client_socket.recv(1024)if not data:break# 打印接收到的消息print(f"来自 {address} 的消息: {data.decode()}")except:print(f"与 {address} 的连接已断开")clients.remove(client_socket)client_socket.close()breaktry:# 等待连接并创建新的线程来处理每个连接while True:client_socket, address = server_socket.accept()client_handler = threading.Thread(target=handle_client, args=(client_socket, address))client_handler.start()# 控制台输入消息并发送给所有客户端while True:message = input("请输入消息: ")for client in clients:client.sendall(message.encode())
except KeyboardInterrupt:print("收到 Ctrl+C,取消端口绑定...")server_socket.close()

bot

import socket
import threadingdef receive_data(sock):while True:try:data = sock.recv(1024)if not data:breakprint(f"Received: {data.decode('utf-8')}")except Exception as e:print(f"Error receiving data: {e}")breakdef main():with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:try:# 连接到服务器client_socket.connect(('127.0.0.1', 8000))print("Connected to server on port 8000.")# 创建一个线程用于接收数据threading.Thread(target=receive_data, args=(client_socket,)).start()while True:# 从控制台读取数据message = input()if message:client_socket.sendall(message.encode('utf-8'))except Exception as e:print(f"Connection error: {e}")if __name__ == "__main__":main()

效果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/758890.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试算法-58-求根节点到叶节点数字之和

题目 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字&#xff1a; 例如&#xff0c;从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。 计算从根节点到叶节点生成的 所有数字之和…

2024年腾讯云优惠券全解析、云服务器代金券领取、查询和使用方法

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

Dockerfile Docker Compose(实战总结)

Dockerfile & Docker Compose&#xff08;实战总结&#xff09; Dockerfile Dockerfile 是用来构建Docker镜像文件&#xff0c;是由一条条构建镜像所需的指令构成的脚步。 步骤&#xff1a; 编写Dockerfile 文件docker build 构建镜像docker run 运行镜像docker push 发…

python coding with ChatGPT 打卡第23天| 回溯算法:理论基础

文章目录 视频讲解回溯法的效率解决的问题如何理解回溯法回溯框架 视频讲解 回溯算法理论篇 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 回溯法的效率 回溯的本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案&#xff0c;如果想让回溯法…

区域规划(Regional Planning)的学习笔记

目录 一、概念题 1.区域的概念、类型、特性 2.区域分析的概念、主要内容 3.自然环境、自然资源的概念 4.区域自然资源评价的内容 5.可持续发展理论定义 6.经济增长、经济结构定义 7.产业结构概念 8.人口增长分析的含义、指标 9.技术进步概念、类型 10.技术进步对区域…

【C++ leetcode】双指针问题(续)

3. 202 .快乐数 题目 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这个过程 结…

ArcGIS Pro、R和INVEST:三位一体的生态系统服务评估框架

生态系统服务是指生态系统所形成的用于维持人类赖以生存和发展的自然环境条件与效用&#xff0c;是人类直接或间接从生态系统中得到的各种惠益。联合国千年生态系统评估&#xff08;Millennium ecosystem assessment&#xff0c;MA&#xff09;提出生态系统服务包括供给、调节、…

智慧水务:雨季山区水域水务智能化监控与监测管理方案

一、方案背景 雨季的水务管理对于各区县来说&#xff0c;无疑是一项至关重要的任务。夏季雨水充沛&#xff0c;江河湖泊水位上涨&#xff0c;山洪、上游排水等情况时有发生&#xff0c;给各地的水务设施和防汛工作带来了严峻的挑战。针对区县的各类水域监管场景&#xff0c;需…

免费的chatgpt网站(包含最新版4.0)

相信每个人在生活工作学习中都逃不过用chatgpt来解决一些问题&#xff0c;下面我长话短说&#xff0c;为大家简单介绍几款免费且好用的chatgpt网站 1、YesChat 网址&#xff1a;YesChat-ChatGPT4V Dalle3 Claude 3 All in One Free 第一个就给大家介绍一个狠角色&#xff0c;最…

C 语言中位取反操作符 ~ 和逻辑取反操作符 !

在 C 语言中&#xff0c;有两种取反操作符&#xff0c;分别是位取反操作符 ~ 和逻辑取反操作符 !。 位取反操作符 ~&#xff1a; 位取反操作符 ~ 是一个一元操作符&#xff0c;用于执行按位取反操作。它会将操作数的每个位取反&#xff0c;即将 0 变为 1&#xff0c;将 1 变为 …

算法打卡day21|回溯法篇01|理论知识,Leetcode 77.组合

回溯法理论知识 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。所以回溯函数也就是递归函数&#xff0c;指的都是一个函数。 回溯法的效率 回溯法并不是什么高效的算法。因为回溯的本质是穷举&#xff0c;…

win提权第二弹服务提权

阅读须知&#xff1a; 探索者安全团队技术文章仅供参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作,由于传播、利用本公众号所提供的技术和信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者 本人负责&#xff0c;作者不为此承担任何责任,如…

使用STM32 再实现电动车防盗

项目需求 点击遥控器 A 按键&#xff0c;系统进入警戒模式&#xff0c;一旦检测到震动&#xff08;小偷偷车&#xff09;&#xff0c;则喇叭发出声响报警&#xff0c; 吓退小偷。 点击遥控器 B 按键&#xff0c;系统退出警戒模式&#xff0c;再怎么摇晃系统都不会报警&…

3.6 条件判断语句cmp,je,ja,jb及adc、sbb指令

汇编语言 1. adc指令 adc是带进位加法指令&#xff0c;它利用了CF位上记录的进位值指令格式&#xff1a;adc 操作对象1&#xff0c;操作对象2功能&#xff1a;操作对象1 操作对象1 操作对象2 CF例如&#xff1a;adc ax,bx&#xff0c;实现的功能是&#xff1a;ax ax bx …

PyCharm中设置代码模版

前言 新创建一个.py文件后&#xff0c;我们总需要在开头写一些必要的代码&#xff0c;有什么方法能够一劳永逸&#xff0c;让这些代码自动生成呢&#xff1f; 有&#xff0c;它就是代码模版。 设置代码模版 这里先说说如何设置它。 步骤&#xff1a;首先打开PyCharm&#xff0…

MySQL介绍

一、MySQL数据库介绍 1、发展史 1996年 MySQL1.0 2008年1月16日 Sun公司收购了 MySQL 2009年4月20日 Oracle收购了Sun公司 MySQL是一种开放源代码的关系型数据库管理系统 使用最常用的数据库管理语言 SQL&#xff08;结构化查询语言&#xff09; MySQL是开放源代码的 因此所有…

【Kotlin】扩展属性、扩展函数

1 类的扩展 Kotlin 提供了扩展类或接口的操作&#xff0c;而无需通过类继承或使用装饰器等设计模式&#xff0c;来为某个类添加一些额外的属性或函数&#xff0c;我们只需要通过一个被称为扩展的特殊声明来完成。通过这种机制&#xff0c;我们可以将那些第三方类不具备的功能强…

C语言例3-35:长度运算的例子

长度运算符的表现形式&#xff1a; sizeof(数据类型符&#xff09; 或 sizeof(变量&#xff09; 长度运算符的优先级&#xff1a; 与单目算术运算符、单目逻辑运算符、自增和自减运算符的优先级相同。上述优先级相同的运算符的结合性都是从右至左。 长度运算的例子 代码如…

二手交易平台|基于JSP技术+ Mysql+Java+ B/S结构的二手交易平台设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

关于在ArkTS中添加动画没有效果这件事

先来看看错的 Entry Component struct an {State a : number 0;State ang : number 0;build() {Row(){Text(^_^).fontSize(90).position({x : 0,y : this.a}).rotate({angle : this.ang,centerX : 50%,centerY : 50%}).onClick(() > {this.a 100;}).animation({duration…