**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