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()
posted @ 2016-07-16 01:49  bigloong  阅读(185)  评论(0编辑  收藏  举报