最近想实现一个关于socket长连接但是一个服务端只能实现一个链接,这可怎么办呢???????
基于多线程实现
自己写的垃圾框架 贼垃圾
第一开始的时候我想用async协程去实现
因为用多线程的话真的觉得不合适,因为我现在写的这个项目是需要和N多个设备进行长连接的,就不断开了!
这.....万一来了N个客户端,岂不是N+1个线程。这可不行啊
基于async实现的思路
其实我还没撸出来基于async的代码但是我已经想好了。我在这里说明一下
1.阻塞都在哪里进行阻塞 accept 阻塞等待新的客户端,以及等待老的客户端recv消息
我也不知道我的思路对不对,我先说一下 过几天我就亲自实现一下然后将代码奉上
socket还是作为全局对象,然后还是老样子创建一个客户端的容器用来存放用户端
紧接着创建一个携程函数,里面while这监听,同样创建一个携程函数一直监听收消息
在创建一个携程函数用来await一下收消息的函数,创建main函数将监听用户注册到loop事件循环中
我也不知道对不对,过几天实现来验证吧。
基于epoll实现
说一下关于epoll实现的
系统分为用户态和内核态 下面是自己最通俗理解的不知道准确与否 欢迎指点
用户态:你自己的程序在没有操作操作系统的内东西的时候
内核态:操作系统
如果socket让操作系统去监听有没有人去链接你呢? 有人链接你的时候操作系统来告诉你有人链接你了,可以处理了
这样循环的时候并不是你自己的程序进行循环,而是操作系统
同步与异步的IO操作
同步
import time
def long_io():
print("开始执行耗时操作")
time.sleep(2)
print("完成执行耗时操作")
result = 'io result'
return result
def work1():
print(" 开始处理work1请求操作 ")
ret = long_io()
print(ret)
print('完成处理work1请求')
def work2():
print("开始处理work2")
print("处理work2请求完成")
def main():
work1()
work2()
if __name__ == '__main__':
main()
异步
import time
from threading import Thread
def long_io(cb):
def fun(callback):
print("开始执行耗时操作")
time.sleep(3)
print("完成执行耗时操作")
result = 'io result'
callback(result)
return "123"
thread = Thread(target=fun, args=(cb,))
thread.start()
def on_finish(ret):
print("1231231231")
print(ret)
print("1231231231")
def work1():
print(" 开始处理work1请求操作 ")
ret = long_io(on_finish)
print(ret)
print('完成处理work1请求')
def work2():
print("开始处理work2")
# time.sleep(2)
print("处理work2请求完成")
def main():
work1()
work2()
if __name__ == '__main__':
main()
IO多路复用模型
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4c16c64b771948348297f89d0e3bf004.png)
反正就是将耗时操作交给系统处理吧 主程序处理主程序应该处理的问题 至于原理的话本人只知道个理解
并不能进行教学 有兴趣的话自行百度
参阅python的文档
# select
import selectors
# socket
import socket
# time
import time
# 线程
import threading
from threading import Thread
server = socket.socket()
server.bind(("0.0.0.0", 8200))
server.listen(5)
epoll = selectors.EpollSelector()
# 客户端存放
server_lst = []
def new_func(conn):
data = conn.recv(1024)
if data == b'':
#删除轮训对象正在跟踪的文件描述符
epoll.unregister(conn)
conn.colse()
else:
print("收到的数据是:%s" % data.decode())
conn.send(data)
def func(ser):
conn, addr = ser.accept()
global server_lst
server_lst.append(conn)
print("来了一个链接")
# 查看是否有数据
print(server_lst)
# 将此对象注册到epoll中,最后一个则是事件对象第二个是事件类型
epoll.register(conn, selectors.EVENT_READ, new_func)
def main():
time.sleep(1)
# 将socket注册 要是来链接后唤醒
epoll.register(server, selectors.EVENT_READ, func)
while True:
# 实例化注册文件列表
events = epoll.select()
# 循环注册文件列表 key是文件对象的实例化,而mask则是事件位掩码
for key, mask in events:
# 实例化回调函数
callback = key.data
将已注册的文件对象拿出来
sock = key.fileobj
# 运行回调方法
callback(sock)
# 主程序创建辅助线程去管理
thread = Thread(target=main)
thread.setDaemon(True)
thread.setName("辅助线程")
thread.start()
# 主程序逻辑
while True:
num = input("请输入:")
_ = {
"1": lambda: print(server_lst),
"2": lambda: print(threading.enumerate()),
}.get(num, None)()