一 .socketserver 模块初级使用(解决并发异步 多用户登录)
ThreadingTCPServer
https://www.cnblogs.com/yuanchenqi/articles/9534816.html
ocketserver是标准库中的一个高级模块
socketserver可以简化创建客户端跟创建服务端的代码
socketserver 可以用于 TCP 协议
应用场景
应为tcp是一个长连接 只能保持一个人通话 但是socketserver就解决了同时多个客户端来 通话
初始化控制器类Handler【Handler是一个继承BaseRequestHandler的类Handler中的handle方法决定了每一个连接过来的操作】
【控制器类的类名可以是其他的,不一定是Handler,只要继承了BaseRequestHandler就行】
init():初始化控制设置,初始化连接套接字,地址,处理实例等信息
handle(): 定义了如何处理每一个连接。
setup(): 在handle()之前执行.一般用作设置默认之外的连接配置
finish():在handle()之后执行。
server1 import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): # print(self.request) self.request相当 socket 服务器端的conn self.ret=self.request.recv(1024) print(self.ret.decode("utf-8")) user=input("我是服务器:") self.request.send(user.encode("utf-8")) if __name__=="__main__": server=socketserver.ThreadingTCPServer(("192.168.59.1",8600),Myserver) # 线程 server.serve_forever() # bind listen # conn,addr=accept # self.request=conn
client1 import socket clinet=socket.socket() clinet.connect(("192.168.59.1",8600)) name=input("我是客户端:") clinet.send(name.encode("utf-8")) ret=clinet.recv(1024).decode("utf-8") print(ret)
# def handle(self): 注意这个self 包含了两个参数 第一个参数信息(self.request==conn) 第二个参数是地址(self.client_address=addr)
server2 import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): self.data = self.request.recv(1024).strip() self.request.sendall(self.data.upper()) print(self.data.decode("utf-8")) print(self.client_address[0]) # self.client_address 地址里面包含ip 端口 是以元祖的形式 if __name__ == "__main__": HOST, PORT = "127.0.0.1", 9999 # 设置allow_reuse_address允许服务器重用地址 socketserver.TCPServer.allow_reuse_address = True # 创建一个server, 将服务地址绑定到127.0.0.1:9999 server = socketserver.TCPServer((HOST, PORT),Myserver) # 让server永远运行下去,除非强制停止程序 server.serve_forever()
client2 import socket HOST, PORT = "127.0.0.1", 9999 data = "hello" # 创建一个socket链接,SOCK_STREAM代表使用TCP协议 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.connect((HOST, PORT)) # 链接到客户端 sock.sendall(data.encode("utf-8")) # 向服务端发送数据 received = sock.recv(1024).decode("utf-8")# 从服务端接收数据 print(data) print(received)
二 .剖析soketserver(源码)
https://www.cnblogs.com/Eva-J/p/5081851.html
1.soketserver(类似里面继承关系)
#_*_coding:utf-8_*_ __author__ = 'Eva_J' class Base(object): def Testfunc(self): print('do Base Testfunc') class Son(Base): def __init__(self,name): self.name = name self.Testfunc() def Testfunc(self): print( 'do Son Testfunc') class Base2(object): def Testfunc(self): print ('do Base2 Testfunc') class GrandSon(Base2,Son): pass #sonobj = Son('sonobj') sonobj = GrandSon('哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇') print(sonobj.name) sonobj.Testfunc() 看上面的代码,我们猜测一下,执行之后,控制台会打印什么呢?先揭晓答案,会打印Base2方法中的内容,原因很简单: 尽管这三个类中都有同样的Testfunc方法,但是,由于计算机在找方法的时候, 遵循的顺序是:Base2,Son,Base,所以它会先找到Base2类,而这个类中刚好有它要找的方法,它也就欢欢喜喜的拿去执行啦! print(GrandSon.__mro__) print(GrandSon.__bases__) print(GrandSon.__name__) print(GrandSon.__dict__) print(sonobj.__dict__) print("*****************************************************************************************************8") #_*_coding:utf-8_*_ __author__ = 'Eva_J' class Base(object): def __init__(self,name): self.name = name self.Testfunc() def Testfunc(self): print ('do Base Testfunc') class Son(Base): def Testfunc(self): print ('do Son Testfunc') sonobj = Son('sonobj') # 果这样看,我们是不是就明白了?其实这两段代码表示的是一个意思,尽管Son继承了Base类,父子类中都有同样的方法, # 但是由于我们实例化了子类的对象,所以这个在初始化方法里的self.Testfunc,self指的是子类的对象,当然也就先调用子类中的方法啦 # 。所以尽管在第一个例子中,初始化方法在父类执行,但是还是改变不了它是子类对象的本质, # 当我们使用self去调用Testfunc方法时,始终是先调用子类的方法。我们可以这样理解, # 尽管儿子继承了父亲的财产,但是花钱的时候,还是要先花自己的~~~
# 注意这个self 包含了两个参数 第一个参数信息(self.request==conn) 第二个参数是地址(self.client_address=addr)