zoukankan      html  css  js  c++  java
  • 10 Socket(二)

    1. 作用域

    1.1 作用域

    代码1

    if 1 == 1:
        name = 'alex'
    for i in range(10):
        name = i
    print(name)
    
    # Java/C#            不可以
    # Python/JavaScript  可以
    # Python中无块级作用域

    代码2:函数

    def func():
        name = 'alex'
    print(name)
    
    def func():
        name = 'alex'
    func()
    print(name)
    
    # Python中以函数为作用域

    代码3:

    name = 'alex'
    
    def f1():
        print(name)
    def f2():
        name='eric'
        f1()
    
    f2()
    # Python的作用域在执行之前已经确

    代码4:

    name = 'alex'
    
    def f1():
        print(name)
    
    def f2():
        name = 'eric'
        return f1
    
    ret = f2()
    ret()
     
    # Python作用域链,由内向外找,直到找不到报错

    代码5:

    li = [x+100 for x in range(10) if x>6]
    print(li)

    代码6:

    li = [lambda :x for x in range(10)]
    r = li[0]()
    
    print(r)
    
    # 剖析
    # li类型:列表
    # li列表中的元素:[函数, 函数, 函数...]
    # 函数在没有执行前,内部代码不执行
    # li[0],lambda函数
    # 函数(),执行函数
    # 返回值:9

    代码7:

    li = []
    for i in range(10):
        def f1():
            return i
        li.append(f1)
    
    print(li[0]())
    print(li[1]())
    print(li[2]())
    # 输出结果
    # 9
    # 9
    # 9
    
    
    li = []
    for i in range(10):
        def f1(x=i):
            return x
        li.append(f1)
    
    print(li[0]())
    print(li[1]())
    print(li[2]())
    
    # 输出结果
    # 0
    # 1
    # 2

    PS:本质上看代码是否执行

    1.2 小结

    • Python中无块级作用域
    • Python中以函数为作用域
    • Python作用域链,由内向外找,直到找不到报错
    • Python的作用域在执行之前已经确定

     1.3 Python多继承2.7版本与3.5版本

    • Python 3所有的类都默认继承object,称新事类
    • Python 2所有的类默认不继承object,称经典类

    2. SocketServer及IO多路复用

    2.1 socketserver基本执行过程

    import socketserver
    
    class MyClass(socketserver.BaseRequestHandler):
    
        def handle(self):
            pass
    
    obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyClass)
    obj.serve_forever()
    
    
    # 创建socket对象
    # accept 处理请求
    # server_address = ('127.0.0.1', 9999)
    # RequestHandlerClass = MyClass  == ()
    # self.RequestHandlerClass() = MyClass()  == ()
    # 1.obj封装了self.RequestHandlerClass = MyClass
    # 2.创建了socket, bind, lister

    2.2 通过IO多路复用实多并发

    概述:

    IO多路复用不占用CPU

    select,poll,epoll  (支持所有IO操作,不支持文件操作)

    监听socket对象内部是否变化了?

    什么时候变化?连接或收发消息

    服务器端的socket发生变化,表示有新连接来了

    sk: 有新连接来了

    conn: 要收发消息了

    IO多路复:监听socket对象内部是否变化了

    1) 多并发连接实现

    server

    import socket
    import select
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 999, ))
    sk.listen(5)
    
    while True:
        rlist,w,e, = select.select([sk,], [], [], 1) #1为超时时间
        print(rlist)
        # rlist中socket对象列表,[sk, ]
        # 有新连接 rlist = [sk]
        # 无连接 rlist = []
    
        for r in rlist:
            print(r)
            conn, address = r.accept() 
            conn.sendall(bytes('hello', encoding='utf-8'))

    client

    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 999, ))
    
    data = sk.recv(1024)
    print(data)
    
    while True:
        input(">>>")
    sk.close()

    2) IO多路复用实现伪并发,可收发消息

    Server

    import socket
    import select
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 999, ))
    sk.listen(5)
    
    inputs = [sk,]
    while True:
        rlist,w,e, = select.select(inputs, [], [], 1) #1为超时时间
        print(len(inputs), len(rlist))
        # 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,些时rlist值为[sk]
        # 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,些时rlist的值为[客户端]
        # rlist中socket对象列表,[sk, ]
        # 有新连接 rlist = [sk]
        # 无连接 rlist = []
    
        for r in rlist:
            if r == sk:
                # 新客户来连接
                conn, address = r.accept()
                # conn是什么?其实也是socket对象
                inputs.append(conn)
                conn.sendall(bytes('hello', encoding='utf-8'))
            else:
                # 有人给我发消息了
                r.recv(1024)

    Client

    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 999, ))
    
    data = sk.recv(1024)
    print(data)
    while True:
        inp = input(">>>")
        sk.sendall(bytes(inp, encoding='utf-8'))
    sk.close()

    3) 读写分离实现

    Server

    import socket
    import select
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9998, ))
    sk.listen(5)
    
    inputs = [sk,]
    outputs = []
    
    while True:
        rlist,wlist,e, = select.select(inputs, outputs, [], 1) #1为超时时间
        print(len(inputs), len(rlist), len(wlist), len(outputs))
        # 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,些时rlist值为[sk]
        # 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,些时rlist的值为[客户端]
        # rlist中socket对象列表,[sk, ]
        # 有新连接 rlist = [sk]
        # 无连接 rlist = []
    
        for r in rlist:
            if r == sk:
                # 新客户来连接
                conn, address = r.accept()
                # conn是什么?其实也是socket对象
                inputs.append(conn)
                conn.sendall(bytes('hello', encoding='utf-8'))
            else:
                # 有人给我发消息了
                try:
                    ret = r.recv(1024)
                    if not ret:
                        raise Exception('断开连接')
                    else:
                        outputs.append(r)
                except Exception as e:
                    inputs.remove(r)
    
        # 所有给我发过消息的人
        for w in wlist:
            w.sendall(bytes('response', encoding='utf-8'))  #回复消息
            outputs.remove(w) # 删除已回复消息的人

    Client

    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9998, ))
    
    data = sk.recv(1024)
    print(data)
    while True:
        inp = input(">>>")
        sk.sendall(bytes(inp, encoding='utf-8'))
        print(sk.recv(1024))
    sk.close()

    4) 回复收到的消息

    Server

    import socket
    import select
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9998, ))
    sk.listen(5)
    
    inputs = [sk,]
    outputs = []
    messages = {}
    
    # del messages[alex] #删除alex的消息
    # message = {
    #     alex:[msg1, msg2, ]
    #     eric:[msg1, msg2, ]
    # }
    
    while True:
        rlist,wlist,e, = select.select(inputs, outputs, [], 1) #1为超时时间
        print(len(inputs), len(rlist), len(wlist), len(outputs))
        # 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,些时rlist值为[sk]
        # 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,些时rlist的值为[客户端]
        # rlist中socket对象列表,[sk, ]
        # 有新连接 rlist = [sk]
        # 无连接 rlist = []
        for r in rlist:
            if r == sk:
                # 新客户来连接
                conn, address = r.accept()
                # conn是什么?其实也是socket对象
                inputs.append(conn)
                messages[conn] = []
                conn.sendall(bytes('hello', encoding='utf-8'))
    
            else:
                # 有人给我发消息了
                try:
                    ret = r.recv(1024)
                    if not ret:
                        raise Exception('断开连接')
                    else:
                        outputs.append(r)
                        messages[r].append(ret)
                except Exception as e:
                    inputs.remove(r)
                    del messages[r]
    
        # 所有给我发过消息的人
        for w in wlist:
            msg = messages[w].pop()
            resp = msg + bytes('response', encoding='utf-8')
            w.sendall(resp)  #回复消息
            outputs.remove(w) # 删除已回复消息的wlist

    Client

    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9998, ))
    
    data = sk.recv(1024)
    
    print(data)
    
    while True:
        inp = input(">>>")
        sk.sendall(bytes(inp, encoding='utf-8'))
        print(sk.recv(1024))
    sk.close()
    

    ThredingTCPServer源码剖析

    PS:所有查找都要遵循一切从原点开始

    第3章 进程与线程

    3.1 多线程多进程

    概述:

    1、一个应用程序,可以有多进程和多线程

    2、默认:单进程,单线程

    3、单进程,多线程

    l  IO操作,不占用CPU

    多线程提高并发

    l  计算性操作,占用CPU

                   多进程提高并发

    4、GIL,全局解释器锁

    小结:

    1. 多线程多进程的目的提供并发
    2. IO密集型:多线程
    3. 计算密集型:多进程

    PS:IO操作,不占用CPU  GIL,全局解释器锁

    3.2 如何建立多线程

    练习创建主线程,子线程

    import threading
    
    t = threading.Thread(target=f1, args=(123,))
    t.start() #不代表当前纯种会被立即执行
    f1(111) #主线程

    基本配置参数

    import threading
    
    t = threading.Thread(target=f1, args=(123,))
    t.setDaemon(True) # true,表示主线程不等此子线程
    t.start() # 不代表当前纯种会被立即执行
    t.join(5)  # 表示主线程至此,等待....,直到子线程执行完毕
               # 参数:表示主线程最多等待时间n秒
    
    # f1(111) #主线程
    print('end')
    print('end')
    print('end')
    print('end')
    

      

    import socketserver

    class MyClass(socketserver.BaseRequestHandler):

    def handle(self):
    pass

    # 创建socket对象
    # accept 处理请求
    # server_address = ('127.0.0.1', 9999)
    # RequestHandlerClass = MyClass == ()
    # self.RequestHandlerClass() = MyClass() == ()
    # 1.obj封装了self.RequestHandlerClass = MyClass
    # 2.创建了socket, bind, lister
    obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyClass)
    obj.serve_forever()
  • 相关阅读:
    好用的辅助工具
    摆脱单体架构黑洞>>>>走向微服务的乐园
    什么是 jQuery 事件
    WebDriver一些常见问题的解决方法【转】
    IE浏览器相关的问题及解决方案[转]
    fix org.openqa.selenium.NoSuchWindowException when find element on ie11.
    BI案例:BI在连锁零售业应用(ZT)【转】
    SQL 基础语法(创建表空间、用户、并授予权限、数据的增删改查) --(学习笔记)[转]
    创建数据库和表的SQL语句【转】
    T-sql语句中GO的作用及语法【转】
  • 原文地址:https://www.cnblogs.com/Liangdalong/p/5675167.html
Copyright © 2011-2022 走看看