八. 网络编程( socketserver 模块 初级使用)

时间:2022-05-18 23:58:30

一 .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)