2020/01/15 01-socketserver版群聊实现

在这里插入图片描述
**socket库本身太过于低级,太过于原始,所以python在原始的socket编程上做了封装,用起来比较方便,这个封装代表python整个流派风格。
**
sockserver有自己的继承关系
从最底层的BaseServer做完善
子类TCPServer,UDPServer是同步 ,用的比较多
引出了UnixStreamServer,UnixDatagramServer

同步就要等前面的链接完成了才能做下面的,指的是accept请求,只能为你服务,服务完再到下面去服务
在这里插入图片描述
同步是不适合开发的,所以有Mixin类,异步
一个Forking多进程
一个Threading多线程
大多数多线程够用了,一般访问都是IO密集型的,所以用Threading,Threading有两类,TCP和UDP,TCP用的多
在这里插入图片描述
首先要了解BaseServer提供了哪些编程接口,用这个来启动一个server,(地址,端口,requesthandlerclass数据处理)
在这里插入图片描述
传输这个类也是有要求的,这个是有约定的,这个类可以从某个类继承
在这里插入图片描述
socketserver编程更像是框架编程,把该写的东西写好了
在这里插入图片描述
把类保存下来作为自己的属性,实例初始化需要传递几个规定的参数
(request其实就是socket,client_address对端地址端口,self=server本身实例对象

在这里插入图片描述这就是那三个参数
在这里插入图片描述在这里插入图片描述

baserequesthandler定义了处理流程,每个链接accept过来以后,分配新的socket,都算一个链接,把链接里面的处理交给handler函数,每个链接创建一个实例来处理,把自己写的handle,每个链接都要实例化来处理,每个链接用这个handle负责处理请求在这里插入图片描述
这个链接处理就这几行,请求来了之后就先调用setup,然后handle,然后finish,一个对象创建之后就开始调用三个函数,处理完之后,这个链接结束
在这里插入图片描述
在这里插入图片描述
上面的是一次性的
在这里插入图片描述
如何长久,能不能阻止立即结束,在里面写循环,可以反复接收请求
在这里插入图片描述在这里插入图片描述
首先要利用server,threading还是forking,tcp还是udp的,选择相应的server,server都是要绑定的,对外提供服务,还需要把对端数据进行处理,handler这个类定义好提交,
最后会在server上调用handle_request()和server_forever()方法
最后关闭server_close,把资源清理

在这里插入图片描述在这里插入图片描述handle循环,进行接收发在这里插入图片描述在这里插入图片描述

改写ChatServer

在这里插入图片描述
ChatServer之前有TCP的版本,改造成一个多线程的tcpserver来解决问题

复制之前写过的
在这里插入图片描述
粘贴给来在这里插入图片描述在这里插入图片描述在这里插入图片描述

按照现在的写法,上面的应该没必要这么多
把socketserver加上去
在这里插入图片描述
创建一个server
在这里插入图片描述
把这两个东西传进来
在这里插入图片描述
会阻塞,所以开一个线程,server_forever永久启动起来
在这里插入图片描述
请求来了给handle处理,虽然父类的方法什么也没有,但是这是个好习惯super().在这里插入图片描述
写群聊之前,先试试单聊在这里插入图片描述
可以把清理工作写在finish,close是setup和handle finish之后,会在适当时机把socket清理掉
在这里插入图片描述
这样把前面复制部分删除
在这里插入图片描述在这里插入图片描述
关闭的时候等几秒
在这里插入图片描述
运行一下看看
在这里插入图片描述
创建客户端链接 在这里插入图片描述
ack是定义的消息在这里插入图片描述
thread1已经创建出来了在这里插入图片描述
现在用的ThreadTcpServer,是一个并行的解决方案,再链接一个客户端
在这里插入图片描述
现在不是群发,是单聊在这里插入图片描述
现在两个都断开
在这里插入图片描述
写了两个同步类,TCPServer,UDPServer,然后用mixin类,就可以具备THreading多线程,forking,多进程

request是参数传进来的,client address也是传进来的,
在这里插入图片描述self是server本身
在这里插入图片描述
baserequest handler 定义的就是一套流程在这里插入图片描述
现在改成群聊,要记录客户端

setup是执行一次,请求是反复用这个链接,没必要每个请求来都要重新做一次,如果再handler函数不循环,实例处理完就没有,每个实例执行流程是先setup,后handle,最后一定finish在这里插入图片描述
再有请求来,setup是不会执行的,setup执行一次,finish执行一次,如果下一个链接来了,就会再次创建一个handle
在这里插入图片描述
如果链接还在,请求来了之后会直接找handle,从缓冲区读数据在这里插入图片描述
但是另外一个链接进来,也会自己创建一个clients,所以这个就不适合作为实例的属性
在这里插入图片描述
有多少个客户端这个数据对所有hanle来说应该都是唯一的,类的定义是唯一的
在这里插入图片描述
也可以server上动态增加一个
在这里插入图片描述
实例化以后,紧接初始化函数,在setup之前是可以拿到client_address在这里插入图片描述
把socket记录进去在这里插入图片描述
离开的时候把相关的清理了在这里插入图片描述
知道handle可能出错,就最后finally一定会执行finish,清理工作一定会执行在这里插入图片描述
values存的都是self.request,request就是socket在这里插入图片描述
执行一下
在这里插入图片描述
链接两个客户端在这里插入图片描述
有两个线程
在这里插入图片描述
都发送消息
在这里插入图片描述
这样就行了
在这里插入图片描述
这样就比原来省事多了,关键要测试handle,循环和不循环什么效果,要了解TCPServer(同步阻塞)和ThreadTCPServer(并行)什么差异
在这里插入图片描述
在这里插入图片描述
不是所有函数都能这么写在这里插入图片描述
客户端主动断开后,会在server端的socket上,会收到空串,
socket断开后,这里的recv不阻塞了,就直接向下走,data什么都没拿到,就是空串,所以加判断,遇到空子节就退出
在这里插入图片描述
框架的好处是,底层繁琐的处理都交给框架处理了,只是把数据处理部分交给你,由你自己来完成在这里插入图片描述
肯定能执行到,因为有 try finally保证的
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
主动断开有两种解决方案,有一个空串的问题
在这里插入图片描述在这里插入图片描述
data=空串等于false
在这里插入图片描述

总结

为每一个链接提供RequestHandlerClass类实例,依次调用setup、handle、funish方法,且使用了try。。finally结构保证finish方法一定能执行。如果要维持链接不退出,只要死循环handle即可。
socketserver模块提供了不同的类,但是编程接口几乎一样,即使是多进程、多线程的类也是一样,大大减少了编程的难度。只需要关注数据处理本身即可,在关键的地方写你的类即可

在这里插入图片描述

写一个handler类,server启动的时候要传两个,一个是地址端口,一个是hanler类,下面只需要去super.handle。最后super.close,hanler类里面有三个东西,setup,handle,finish,try…finally保证,hanle循环。
三个属性,request,client_address,socket

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值