网络编程——python

网络基本概念:

    1、主机:

    2、端口:

    3、ip:

    4、缓冲区功能:协调读写速度,减少和磁盘交互.

    5、文件描述符:每一个IO操作系统都会为其分配一个不同的正整数,该正整数即为此IO操作的文件描述符。通常从3开始往后排.

    6、高内聚:单个模块功能尽量单一

    7、低耦合:模块之间尽量减少关联和影响

    8、协议(网络协议):在网络通信中,各方必须遵守的规定。包括建立什么样的连接,消息结构等。

    9、https:HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

    10、IO密集型程序:程序的执行过程中进行大量的IO操作,而只有较少的cpu运算。消耗计算机资源较少,运行时间长。

    11、CPU密集型程序(计算密集型):程序运行中需要大量CPU运算,IO操作较少。消耗CPU资源多,运行速度快。

    12、五元组:源IP地址、源端口、目的IP地址、目的端口、传输层协议这五个量组成的集合。

 

 

osi七层模型:

    应用层:提供用户服务,具体内容由特定程序规定

    表示层:数据的压缩优化

    会话层:建立应用连接,选择传输层服务

    传输层:提供不同的传输服务,流量控制

    网络层:路由选择,网络互连

    链路层:提供链路交换,具体消息以帧发送

    物理层:物理硬件,接口网卡线路

 

 

协议都有哪些:

    应用层:TFTP HTTP DNS SMTP

    传输层:TCP UDP

    网络层:IP

    物理层:IEEE

 

 

三次握手和四次挥手:

    三次握手:建立数据传输两端的持续连接:

        1、客户端向服务器发起连接请求

        2、服务器收到连接请求进行确认,返回报文

        3、客户端收到服务器确认进行连接创建

 

    四次挥手:断开连接的两端,保证数据的传输完整

        1、主动方发送报文,告知被动方要断开连接

        2、被动方返回报文,告知收到请求,准备断开

        3、被动方再次发送报文,告知准备完毕可以断开

        4、主动方发送报文完成断开

 

 

tcp流式套接字 和 udp数据报套接字 的区别:

    协议的层面上的区别:

        1、tcp提供可靠的传输服务,可靠性表现在:数据在传输过程中,无失序、无差错、无重复、无丢失;udp不保证传输的可靠性

        2、tcp传输过程中有建立和断开连接的过程:三次握手和四次挥手;udp无需建立三次握手和四次挥手的连接断开过程

        3、tcp适合文件的上传下载,网络情况良好;udp网络情况较差,对可靠性要求不高,收发消息的两端不适合建立固定连接

 

    编程的层面上的区别:

        1、流式套接字采用字节流的方式传输数据,而数据报套接字以数据报形式传输

        2、tcp会产生粘包现象,udp消息是有边界的,不会粘包

        3、tcp传输是建立在连接的基础上,保证传输的可靠性,而udp一次接收一个数据报,不保证完整性

        4、tcp需要依赖listen、accept建立连接,udp不用

        5、tcp收发消息使用recv、send,udp用recvfrom、sendto

 

 

套接字:

    tcp流式套接字:

        服务端流程:

            from socket import *

            创建套接字:sockfd=socket(AF_INET,SOCK_STREAM)

            绑定服务端地址:sockfd.bind(('127.0.0.1',8888))

            监听套接字:sockfd.listen(2)

            创建连接:connfd,addr=sockfd.accept()

            接收消息:data=connfd.recv(1024)

            发送消息:n=connfd.send(b'Receive your message\n')

                    print('Send %d bytes data'%n)

            关闭连接套接字:connfd.close()

            关闭服务端套接字:sockfd.close()

        客户端流程:

            创建套接字:sockfd=socket()

            发起连接请求:sockfd.connect(('172.0.0.1',8888))

            发送信息:sockfd.send(data.encode())

            接收信息:data=sockfd.recv(1024).decode()

            关闭套接字:sockfd.close()

        补充:

            sendall():

                功能:同send() 作为tcp消息发送

                参数:同send()

                返回值:发送成功返回None,发送失败返回异常

        recv()特性:

            1、如果连接断开,recv会立即结束阻塞返回空字符串。

            2、当接收缓冲区为空时会阻塞

            3、如果recv一次接收不完缓冲区内容,下次会继续接收,确保数据不丢失

        send()特性:

            1、如果另一端不存在,仍使用send进行发送,则会产生BrokePipeError异常。

            2、当发送缓冲区满时会阻塞

        tcp粘包:

            产生原因:tcp传输采用字节流的方式,消息之间没有边界,如果发送和接收速度不匹配,会造成多次发送的内容被一次接收,形成意义上的误解即粘包。

            产生条件:当使用send快速的连续发送极有可能产生粘包。

            影响:如果每次发送的内容代表一个独立的意思,此时产生粘包需要处理。但是如果多次发送的内容本身就是一个连续的整体,此时就不需要处理。

            如何处理:

                1、每次发送后加一个结尾标志,接收端通过标志进行判断。

                2、发送一个数据结构

                3、每次发送中间有一个短暂的延迟

 

    udp数据报套接字:

        服务端流程:

            1、创建套接字:sockfd=socket(AF_INET,SOCK_DGRAM)

            2、绑定服务端地址:sockfd.bind()

            3、消息的收发:

                接收:data,addr=sockfd.recvfrom(buffersize)

                发送:n=sockfd.sendto(data,addr)

            4、关闭套接字:sockfd.close()

        客户端流程:

            1、创建套接字:sockfd=socket(AF_INET,SOCK_DGRAM)

            2、消息收发:

                发送:sockfd.sendto('你好'.encode(),('127.0.0.1',8888))

                接收:data,addr=sockfd.recvfrom(buffersize)

 

 

socket模块 和套接字属性

注:s表示一个套接字对象

    属性:

        s.type:获取套接字类型

        s.family:获取地址族类型

 

    函数:

        s.fileno():获取套接字的文件描述符

        s.getsockname():获取绑定地址

        s.getpeername():获取tcp连接套接字另一端的地址

        s.setsockopt(level,optname,value):设置套接字选项,丰富原有套接字功能

            参数:

                level:获取选项的类型SOL、IPP开头都是选项类型

                optname:每个选项类型中的子选项

                value:为选项设置值

         s.getsockopt(level,optname):获取套接字选项的值

 

 

udp套接字应用之广播

    一点发送多点接收

 

 

tcp套接字应用之HTTP传输

    http协议---》超文本传输协议   应用层协议

    用途:网页的获取,给予网站的数据传输,给予http协议的数据传输

    特点:

        1、应用层协议,传输层使用tcp传输

        2、简单灵活,和多种语言对接方便

        3、无状态协议,不记录用户的通信内容

        4、成熟稳定 http1.1

    工作模式:

        1、使用http双方均遵循http协议规定发送接收消息体

        2、请求方,根据协议组织请求内容发送给对方

        3、服务方,收到内容按照协议解析

        4、服务方,将回复内容按照协议组织发送给请求方

        5、请求方,收到回复根据协议解析

    http请求:Request

        请求格式:

            1、请求行

                GET          /           HTTP/1.1

                请求种类    请求内容        协议版本

                请求种类:

                    GET:获取网络资源

                    POST:提交一定的附加数据,得到返回结果

                    HEAD:获取响应头

                    PUT:更新服务器资源

                    DELETE:删除服务器资源

                    CONNECT:预留

                    TRACE:测试

                    OPTIONS:获取服务器性能

            2、请求头:对请求内容的具体描述

            3、空行

            4、请求体:提交具体的请求参数

 

    http响应:Response

        响应格式:

            1、响应行:反馈具体的响应情况

                HTTP/1.1        200         ok

                版本信息        响应码       附加信息

                响应码:

                    1**:提示信息 表示请求已经接受

                    2**:响应成功

                    3**:响应需要重新定向

                    4**:客户端错误

                    5**:服务器错误

                常见响应码:

                    200:成功

                    404:请求页面不存在

                    401:没有访问权限

                    500:服务器发生未知错误

                    503:服务器暂时无法执行

            2、响应头:对响应信息的具体描述

            3、空行

            4、响应体:将客户想要的内容进行返回

 

 

HTTPS和HTTP的区别主要如下:

    1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用;

    2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议;

    3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443;

    4、http的链接很简单,是无状态的;https协议是由ssl+http协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

 

 

IO input output

    凡是在内存中存在数据交换的操作都可以认为是IO操作

    比如:

        内存和磁盘交互  读写 read write

        内存和终端交互     print input

        内存和网络交互     send  recv

IO分类:

    1、阻塞IO

        特点:默认形态 效率很低的一种IO

        阻塞情况:

            1)因为某种条件没有达到造成的阻塞:input accept recv

            2)处理IO事件的时间消耗较长带来阻塞:文件的读写过程、网络数据发送过程

    2、非阻塞IO

        特点:通过修改IO时间的属性,使其变为非阻塞状态,即避免条件阻塞的情况

        非阻塞情况:

            1)往往和循环搭配使用,这样可以不断执行部分需要执行的代码,也不影响对阻塞条件的判断。

                设置套接字为非阻塞:

                    s.setblocking()     异常:BlockingIOError

                        功能:设置套接字的阻塞状态

                        参数:设置为False

                    e.g.:   s.setblocking(False)

                            while True:

                                print('waiting to connect ...')

                                try:

                                    confd,addr=s.accept()

                                except BlockingIOError:

                                    sleep(2)

                                    print(ctime())

                                    continue

 

            2)超时检测:将原本阻塞的IO设置一个最长阻塞等待时间,在规定时间内如果达到条件则正常执行,如果时间到仍未达到条件则结束阻塞。

                s.settimeout(sec) 异常:timeout

                    功能:设置套接字超时时间

                    参数:设置的时间

    3、IO多路复用

        特点:同时监控多个IO时间,当哪个IO时间准备就绪就执行哪个IO事件。此时形成多个IO时间都可以操作的现象,不必逐个等待执行。

        准备就绪:IO事件即将发生的临界状态

        import select:

            select:支持Windows、Linux、Unix

                函数原型:r,w,x=select(rlist,wlist,xlist[,timeout])

                功能:监控IO事件,阻塞等待IO事件发生

                参数:

                    rlist:列表    存放监控被动等待处理的IO事件

                    wlist:列表    存放需要主动处理的IO

                    xlist:列表    存入如果发生异常需要处理的IO

                    timeout:超时时间

                返回值:

                    r:列表    rlist中准备就绪的IO

                    w:列表    wlist中准备就绪的IO

                    x:列表    xlist中准备就绪的IO

                注意事项:

                    1、处理IO的过程中不应该有死循环出现,使一个客户端长期占有服务端。

                    2、IO多路复用是一种并发行为,但是是单进程程序,效率较高

            poll:支持Linux、Unix

                位运算:按照二进制位来进行运算操作

                使用:

                    1、在底层做硬件寄存器的操作,最小单位就是位

                    2、做标志位的过滤选择

                运算符:

                    &:按位与

                    |:按位或

                    ^:按位异或

                    <<:左移

                    >>:右移

                        1 & 1 = 1, 1 | 1 = 1, 1 ^ 1 = 0

                        1 & 0 = 0, 1 | 0 = 1, 1 ^ 0 = 1

                        0 & 1 = 0, 0 | 1 = 1, 0 ^ 1 = 1

                        0 & 0 = 0, 0 | 0 = 0, 0 ^ 0 = 0

                    二进制:

                        1:0001

                        2:0010

                        3:0011

                        4:0100

                        5:0101

                        6:0110

                        7:0111

                        8:1000

                        9:1001

                       10:1010

 

                代码:

                    from select import poll

                    1、创建poll对象

                        p=poll()

                    2、添加关注的IO

                        poll IO 事件分类:

                            POLLIN:rlist被动处理的事件

                            POLLOUT:wlist主动处理的事件

                            POLLERR:xlist错误处理事件

                            POLLHUP:断开连接

                            POLLPRI:紧急处理

                            POLLVAL:无效

                        p.register(s,POLLIN)

                        p.register(s,POLLIN|POLLERR)

                    3、去掉对IO的关注

                        p.unregister(s)

                    4、进行监控

                        events=p.poll()

                            功能:监控关注的IO,阻塞等待IO发生

                            返回值:events是一个列表,列表中每个元素为一个元组,代表准备就绪需要处理的IO

                            events=[(fileno:文件描述符,event:事件),(),()]

                            实施方法:建立比照字典{s.fileno():s}

                    5、

            epoll:支持Linux、Unix

                使用方法:与poll基本相同

                区别:

                    1、生成对象使用epoll() 而不是poll()

                    2、register注册IO事件 事件类型改为epoll事件类型

        select、poll、epoll区别:

            1、select可以很好支持Windows

            2、epoll比select和poll效率高,select和poll差不多

            3、epoll提供了更多的触发方式,EPOLLET

    4、事件IO

    5、异步IO

 

 

本地套接字

    linux 下文件类型:

        b:块设备文件

        c:字符设备文件

        d:目录

        -:普通文件

        l:链接

        s:套接字

        p:管道

 

    作用:用于本地不同程序间进行通信

    本地套接字创建流程:与tcp相似

        1、创建套接字对象

            sockfd=socket(AF_UNIX,SOCK_STREAM)

        2、绑定本地套接字文件

            sockfd.bind(path)

            path:一个文件(字符串)

        3、监听

        4、连接套接字文件

        5、接收发送信息

 

 

多任务编程

    意义:充分的利用计算机资源提高程序的运行效率

    定义:通过应用程序利用计算机的多个核心达到同时执行多个任务的目的,以此来提升程序的执行效率。

    实施方案:多进程 多线程

 

    并行:多个计算机核心在同时处理多个任务,多个任务之间是并行关系。

    并发:计算机同时处理多个任务,内核在多个任务间不断切换,达到好像在同时处理的运行效果。此时多个任务实际为并发关系。

进程:process

    1、程序在计算机中运行一次的过程

    2、进程是一个动态的过程描述,占有cpu内存等计算机资源的,有一定的生命周期

    程序:是一个可执行文件,是静态的,占有磁盘,不占有计算机运行资源

    注:同一个程序的不同执行过程是不同的进程,因为分配的计算机资源等均不同

 

    进程创建流程:

        1、用户空间运行一个程序,发起进程创建

        2、操作系统接受用户请求,开启进程创建

        3、操作系统分配系统资源,确认进程状态

        4、将创建好的进程提供给应用层使用

 

    cpu时间片:

        如果一个进程占有计算机核心,我们称为该进程在cpu时间片上。多个任务实际对cpu会进行争夺,一般由操作系统分配cpu时间

    PCB(进程控制块):

        在操作系统中,进程创建后会自动产生一个空间存放进程信息,称为进程控制块。

    进程信息:

        进程PID,进程占有的内存位置,创建时间,用户。。。

    进程PID:

        进程在操作系统中的唯一编号,大于0的整数,由系统自动分配

    进程信息查看命令:ps -aux

    进程特征:

        1、进程是操作系统分配计算机资源的最小单位

        2、每个进程都有自己单独的虚拟内存空间

        3、进程间的执行相互独立,互不影响。

 

    进程状态:

        三态:

            1、就绪态:进程具备执行条件,等待系统分配cpu

            2、运行态:进程占有CPU处理器,处于运行状态

            3、等待态:进程暂时不具备运行条件,需要阻塞等待,让出CPU

        五态:

            1、新建态:创建一个新的进程,获取资源的过程

            2、就绪态:进程具备执行条件,等待系统分配cpu

            3、运行态:进程占有CPU处理器,处于运行状态

            4、等待态:进程暂时不具备运行条件,需要阻塞等待,让出CPU

            5、终止态:进程结束释放资源的过程

        ps -aux ----->STAT查看进程状态

            D:等待态   (不可中断等待)

            S:等待态   (可中断等待)

            T:等待态   (暂停状态)

            R:运行态   (就绪态、运行态)

            Z:僵尸态   ()

 

            +:前台进程

            <:高优先级

            N:低优先级

            l:有进程链接

            s:会话组组长

 

    进程优先级:

        优先级决定了一个进程的执行权限和占有资源的优先程度。

        查看进程优先级:

            top:动态查看进程优先级               ctrl+左右翻页

                取值范围:-20~19     -20优先级最高

            nice:指定优先级运行程序

                e.g. nice -9 ./while.py

                     sudo nice --9 ./while.py  -9优先级

 

    父子进程:

        在系统中除了初始化进程,每个进程都有一个父进程,可能有0个或者多个子进程。由此形成父子进程关系。我们认为每个进程都是父进程发起请求创建的。

        查看进程树:pstree

        查看父进程PID:ps -ajx  PPID进程ID号

 

    要求:

        1、什么是进程,进程和程序的区别

        2、了解进程的特征

        3、清楚进程的状态及状态间的转化关系

        4、并行和并发的区别,操作系统功能

 

    创建新进程

        import os

        pid = os.fork()

            功能:创建一个新的进程

            参数:无

            返回值:

                失败返回一个负数:-1

                成功:

                    1、在原有进程中返回新的进程的PID

                    2、在新的进程中返回0

        1、子进程会复制父进程全部代码段,包括fork前的代码

        2、子进程从fork的下一句开始执行

        3、父子进程通常会根据fork返回值的差异选择执行不同的代码(使用if结构)

        4、父子进程在执行上互不干扰,执行顺序不确定

        5、子进程虽然复制父进程内存空间,但是有自己的特性,如PID号、PCB等

        6、父子进程空间独立,各自修改各自的内容,互不影响

 

 

    进程的相关函数:

        os.getpid():

            功能:获取当前进程的PID号

            返回值:返回PID号

        os.getppid():

            功能:获取当前进程的父进程PID号

            返回值:返回PID号

        os._exit(status):

            功能:退出进程

            参数:进程的退出状态 整数

        sys.exit([status]):

            功能:退出进程

            参数:默认为0 如果是整数则表示退出状态,如果是字符串,则表示退出时打印字符串。可以通过捕获SystemExit异常阻止退出。

 

    孤儿进程:父进程先于子进程退出,此时子进程就会成为孤儿进程。

        1、孤儿进程会被系统指定的进程收养,即系统进程会成为该孤儿进程新的父进程。

        2、孤儿进程退出时,该父进程会处理退出状态。

 

    僵尸进程:子进程先于父进程退出,父进程没有处理子进程退出状态,此时子进程成为僵尸状态。

        1、僵尸进程已经结束,但是会直流部分PCB信息在内存,大量的僵尸会消耗系统资源,应该尽量避免

 

        父进程处理子进程退出状态

            pid,status=os.wait()

                功能:在父进程中阻塞等待处理子进程的退出

                返回值:

                    pid:退出状态的子进程PID号

                    status:子进程退出状态

            os.WEXITSTATUS(status):

                功能:获取进程退出状态码

            pid,status=os.waitpid(pid,option)

                功能:同wait

                参数:

                    pid

                        -1:表示任意子进程退出

                        >0整数:指定PID号的子进程退出

                    option

                        0:表示阻塞等待

                        WNOHANG:表示非阻塞

                返回值:同wait

 

        父进程先退出

            创建二级子进程

                1、父进程创建子进程等待子进程退出

                2、子进程创建二级子进程,然后马上退出

                3、二级子进程成为孤儿,处理具体事件

                    def fun1():

                        sleep(3)

                        print('第一件事')

                    def fun2():

                        sleep(4)

                        print('第二件事')

 

                    pid = os.fork()

 

                    if pid <0:

                        print("进程创建失败")

                    elif pid ==0:

                        pid0=os.fork()

                        if pid0<0:

                            print("创建二级进程失败")

                        elif pid0==0:

                            fun2()

                        else:

                            os._exit(0)

                    else:

                        os.wait()

                        fun1()

multiprocessing 模块创建进程

    1、需要将要做的事件封装为函数

    2、使用multiprocessing中提供的Process类创建进程对象

    3、通过进程对象和Process初始化函数对进程进行设置,并且绑定要执行的事件

    4、启动进程,会自动执行相关联函数

    5、事件完成后回收进程

 

    最基本使用:

        Process()

            功能:创建进程对象

            参数:

                [name:给创建的进程对象起一个名字]

                target:绑定的函数

                    args:元组(给target函数按照位置传参)

                    kwargs:字典(给target函数按照键值传参

        p.start()

            功能:启动进程,此时进程被创建。自动运行进程函数

        p.join([timeout])

            功能:阻塞等待回收响应的进程

            参数:超时时间

 

    e.g.import multiprocessing as mp

        from time import sleep

 

        def fun():

            sleep(3)

            print("son")

 

        p=mp.Process(target=fun)

        p.start()

        p.join()

 

    特性:

        1、multiprocessing创建进程是原来进程的子进程,创建后父子进程格子执行互不影响

        2、子进程同样是复制父进程的空间,子进程对内容的修改不会影响父进程的空间

        3、join回收子进程,会有效的阻止僵尸进程产生

        4、通常使用multiprocessing创建进程,父进程只用作进程的创建和回收,不做其他工作

 

    multiprocessing进程对象属性:

        p.is_alive()

            功能:判断进程生命周期状态

            返回值:布尔值

        p.name

            功能:进程名称 默认为process-1 如果起名字则为自定义名称

        p.pid

            功能:返回创建子进程的pid

        p.daemon

            功能:

                1、默认值为False,父进程退出不会影响子进程运行

                2、改为True,父进程退出子进程也会退出

            特性:

                1、daemon 的设置必须在start前

                2、如果设置daemon为True 则不再使用join

 

    创建自己的进程类

    1、继承Process类

    2、重写__init__并且调用父类的__init__

    3、重写run方法,此时声称对象后,调用start就会自动运行run

 

多进程:

    优点:

        1、能并行执行多个任务,提高效率

        2、创建方便,运行独立,不受其他进程影响

        3、数据安全

    缺点:

        进程的创建和删除都需要消耗计算机的资源

 

进程池技术:

    产生原因:如果有大量任务需要多进程完成,且可能需要频繁的创建和删除进程,给计算机带来大量的资源消耗。

    原理:在进程池内运行一定数量进程,通过这些进程完成进程池队列中的事件,直到事件执行完毕,减少进程不断的创建删除过程。

 

    实施操作方法:

        1、创建进程池,在进程池中放入适当进程

        2、将事件加入到进程池队列

        3、事件不断运行,直到所有事件运行完毕

        4、关闭进程池,回收进程

 

        from multiprocessing import Pool

 

        pool=Poll(processes)

            功能:创建进程池对象

            参数:表示进程池中有多少进程

        pool.apply_async(func,args,kwds)

            功能:将事件放入进程池列队

            参数:

                func 要执行的事件

                args 给func用元组传参

                kwds 给func用字典传参

            返回值:返回事件对象r

                通过r.get()方法获取事件函数返回值

 

        pool.apply(func,args,kwds)

            功能:将事件放入进程池列队

            参数:

                func 要执行的事件

                args 给func用元组传参

                kwds 给func用字典传参

        pool.close()

            功能:关闭进程池,不能再添加新的事件

        pool.join()

            功能:阻塞等待回收进程池

        pool.map(func,iter)

            功能:将要完成的事件放入进程池

            参数:

                func 要完成的事件函数

                iter 可迭代对象给func传参

            返回值:事件函数的返回值列表

 

进程间通信

    进程间由于空间独立,资源无法互相直接获取,因此在不同的进程间进行数据传递就需要专门的通信方法。

    进程间通信方法(IPC):

        1、管道Pipe

            在内存中开辟一段空间,形成管道结构,管道对多个进程可见,进程可以对管道进行读写操作

            multiprocessing中提供Pipe

            fd1,fd2=Pipe(duplex=True)

                功能:创建一个管道

                参数:默认为双向管道,如果设置为False,则为单向管道

                返回值:

                    双向:fd1、fd2类似于open创建的对象,可进行读写操作

                    单向:fd1只能读,fd2只能写

            fd.recv()

                功能:从管道内读取内容

                返回值:读到的内容,如果管道无内容则阻塞

 

            fd.send(data)

            功能:向管道写入内容

            参数:要发送的内容,几乎可以发送python支持的所有数据类型

 

        2、消息队列

            队列:先进先出

            在进程中开辟队列结构空间,多个进程可以向队列投放消息,在取出的时候按照存入顺序取出

            multiprocessing -->Queue

            q=Queue(maxsize=0)

                功能:创建队列

                参数:maxsize 默认表示根据系统分配空间存储消息,如果传入一个正整数则表示最多存放多少条消息

                返回:队列对象

            q.put(data,[block,timeout])

                功能:存放消息

                参数:

                    data 存入的消息(python数据类型)

                    block:

                        默认True表示当队列满时阻塞

                        设置为False则表示非阻塞

                    timeout当block为True表示超时时间

            data=q.get([block,timeout])

                功能:取出消息

                参数:

                    block:

                        默认为True 当列队空时阻塞

                        设置为False 表示非阻塞

                    timeout:当block为True时,表示是超时时间

                返回值:返回获取的消息

            q.full()    判断队列是否为满

            q.empty()   判断队列是否为空

            q.qsize()   判断当前队列有多少消息

            q.close()   关闭队列

 

        3、共享内存

            在内存中开辟一段空间,存储数据,对多个进程可见。

            每次写入共享内存中的数据会覆盖之前的内容。

            from multiprocessing import Value

            obj=Value(ctype,obj)

                功能:开辟共享内存空间

                参数:

                    ctype:字符串 要转变的c的数据类型  对比类型对照表

                    obj:共享内存的初始化数据

                返回:共享内存对象

            obj.value:表示共享内存中的值。对其修改或者使用即可。

            obj=Array(ctype,obj)

                功能:开辟共享内存

                参数:

                    ctype:要转化的c的类型

                    obj:要存入共享内存的数据

                        列表:将列表存入共享内存,数据类型一直

                        正整数:表示开辟几个数据空间

                返回:数据列表

                读取修改文件:返回对象[index]=newNo.

 

 

        区别:

            类型               管道             消息队列        共享内存

            开辟空间            内存              内存            内存

            读写方式      两端读写(双向或单项)    先进先出       操作覆盖内存

            效率               一般               一般            较快

            应用            多用于两端通信        使用广泛   复杂,需要同步互斥机制

 

 

        4、信号

            一个进程向另一个进程通过信号传递某种讯息,接收方在接收到信号后进行相应的处理

            查看信号:kill -1

            kill -signum PID给PID的进程发送一个信号,kill在这里的意思是发送

            关于信号

                信号名称:信号的名字或者数字

                信号含义:信号的作用

                默认行为:当一个进程接收到信时采取的行为

                    终止行为

                    暂停行为

                    忽略产生

                e.g  import os

                     import signal

                     os.kill(os.getppid(),signal.SIGKILL)

            通过python进行信号处理

 

            os.kill(pid,sig)

                功能:发送信号给某个进程

                参数:

                    pid 给哪个进程发送信号

                    sig 要发送什么信号

            signal.alarm(sec)(异步处理函数)

                功能:一定时间后给吱声发送一个SIGALRM信号

                参数:指定时间

                注意:在一个进程中只能有一个时钟信号,设置后一个时钟会把第一个时钟覆盖掉,sleep会影响信号钟

            异步处理信号:

                当alarm将请求发给内核,内核会记录请求,应用程序会继续执行,不会停止,当条件达成,内核会给应用程序发送信号,应用程序会对信号进行反应,以完成信号传达的信息。条件达成后,进程已结束,内核忽略此信号.

            程序执行的同步和异步

                同步:按照步骤一步一步顺序执行

                异步:在程序执行中利用内核,不影响应用程序持续执行

                信号时唯一的异步通信方式

            signal.pause()

                功能:等待信号(阻塞)

            signal.signal(signum,handler)(异步处理函数)

                功能:处理信号

                参数:

                    signum:要处理的信号

                    handler:信号的处理方法

                        SIG_DFL     表示使用默认的方法处理

                        SIG_IGN     表示忽略这个信号

                        def func(sig,frame)        自定义函数处理信号

                            sig:表示要处理的信号

                            frame:信号的结构对象

                signal函数不能处理SIGKILL SIGSTOP信号

                在父进程中使用signal(SIGCHLD,SIG_IGN),这样子进程退出时会有系统自动处理

 

 

        5、信号量

            给定一定的数量,对多个进程可见,并且多个进程根据信号量的多少确定不同的行为

            multiprocessing---》Semaphore()

                sem=Semaphore()

                    功能:生成信号量对象

                    参数:信号量的初始值

                    返回值:信号量对象

                sem.acquire()

                    功能:信号量数量减1,信号量为0时会阻塞

                sem.release()

                    功能:信号量数量加1

                sem.get_value()

                    功能:获取当前信号量的值

                e.g.    from time import sleep

                        import os

                        from multiprocessing import Semaphore,Process

                        sem=Semaphore(3)

 

                        def fun():

                            print('process %d wait for semaphore'%os.getpid())

                            sem.acquire()

                            print('process %d expend semaphore'%os.getpid())

                            sleep(3)

                            print('process %d add semaphore'%os.getpid())

                            sem.release()

                        jobs=[]

                        for i in range(4):

                            p=Process(target=fun)

                            jobs.append(p)

                            p.start()

 

                        for i in jobs:

                            i.join()

            同步互斥机制

                目的:解决对共有资源操作产生的争夺

                临界资源:多个进程或者线程都能操作的资源

                临界区:操作临界资源的代码段

                同步:是一种合作关系,为完成某个任务,多进程或者多线程之间形成一种协调。按照约定依次执行对临界资源的操作,相互告知相互促进。

                互斥:互斥是一种制约关系,当一个进程占有临界资源就会进行加锁的操作,此时其他进程就无法操作该临界资源。直到使用的进程进行解锁操作后才能使用。

                Event 事件

                multiprocessing--》Event

                创建事件对象

                    e.Event()

                事件阻塞

                    e.wait([timeout])

                事件设置

                    e.set()

                        功能:当e被set()后,e.wait()不再阻塞

                事件清除

                    e.clear()

                        功能:e被clear()后,e.wait()又会阻塞

                事件判断

                    e.is_set()

                        功能:判断当前事件对象是否被设置

            锁 Lock

                multiprocessing--》Lock

                创建对象

                    lock=Lock()

                上锁

                    lock.acquire()

                    上锁状态:执行acquire()操作会阻塞

                解锁

                    lock.release()

                    解锁状态:执行release()不阻塞

 

            with lock:---》上锁

                ……

                ---》with代码块执行结束即解锁

        6、套接字

 

线程

    定义:线程也是一种多任务编程的方式,可以使用计算机多核资源。线程又被称为轻量级的进程。

    特征:

        1、线程是计算机核心分配的最小单位

        2、一个进程可以包含多个线程

        3、线程也是一个运行过程,也要消耗计算机资源。多个线程共享其进程的资源和空间。

        4、线程也拥有自己特有的资源属性,比如指令集,TID等。

        5、线程无论是创建还是删除还是运行,资源消耗都小于进程

        6、多个线程之间并行执行,互补干扰。

    创建线程

        threading模块

        threading.Thread()

            功能:创建线程对象

            参数:

                name:线程名称

                target:线程函数

                args:元组 给线程函数传参

                kwargs:字典 给线程函数传参

        t.start()

            功能:启动线程

        t.join([timeout])

            功能:回收线程

    线程属性

        t.is_alive()查看线程状态

        t.name()线程名称

        t.setName()设置线程名称

        threading.currentThread()获取当前县城对象

        t.daemon 默认情况下,主线程的结束不会影响分支线程,如果设置为True 则主线程退出分支线程也会退出

            设置方法:

                t.daemon=True

                t.setDaemon(True)

            判断daemon属性:

                t.isDaemon()

            注:线程daemon属性的设置在start前

                一般设置daemon后不会再使用join

 

    创建自己的线程类

        1、继承Thread类

        2、运行Thread类中的__init__方法以获取父类属性

        3、重写run方法

    threadpool(线程池,第三方模块)

    线程通信

        通信方法

            多个线程共用进程空间,所以进程的全局变量对进程内的线程均可见。因此使用全局变量通信是线程主要通信方法。

        注意事项

            线程间通信更容易产生资源争夺,往往需要同步互斥机制保证通信安全。

        线程的同步互斥

        threading--》Event()

            操作

                from threading import Thread,Event

                e=Event()

                e.wait([timeout])如果e为设置状态则不阻塞,未设置则阻塞

                e.set()将e变为设置状态

                e.clear()将e设置去除

        线程锁

            lock=threading.Lock()创建锁

            lock.acquire()上锁

            lock.release()解锁

            操作原理:重复上锁acquire会阻塞

    Python线程GIL问题

        GIL:全局解释器锁

        后果:一个解释器,同一时刻只能解释一个线程。并行变并发。大大降低了python多线程的执行效率。

        Python 的GIL问题 解决方案

            1、尽量使用进程

            2、不使用c作为解释器

            3、Python线程适用于高延迟的IO操作,网络操作,不适合cpu密集型或者传输速度很快的IO操作

            注意:线程遇到阻塞会让出解释器

进程线程区别联系:

    1、两者都是多任务编程方式,都能使用计算机多核资源

    2、进程的创建和删除要比线程消耗更多的计算机资源

    3、进程空间独立,数据安全性好,有专门的通信方法

    4、线程使用全局变量通信,更加简单,但往往需要同步互斥

    5、一个进程可以包含多个线程,线程共享进程的资源

    6、进程线程都有自己的特有属性资源,如命令,属性,id等

使用场景:

    1、如果需要创建较多的并发,任务比较简单,线程比较合适

    2、如果数据和功能比较独立,此时使用进程比较合适

    3、使用线程时要考虑到同步互斥的复杂程度

    4、python线程需要考虑到GIL问题

服务器模型

    硬件服务器:主机 集群

        厂商:IBM HP 联想 浪潮

    软件服务器:

        编写的服务端程序,依托于硬件服务器运行,提供给用户一定的软件服务。

        分类:

            webserver:网络后端程序提供网站请求的后端处理和响应

            httpserver:处理http请求,回复http响应

            邮箱服务器:处理邮件

            文件服务器:处理文件传输

        功能:

            网络连接

            逻辑处理

            数据的交互

            数据的传输

            协议的实现

        模型结构:

            c/s:客户端服务器模型

            b/s:浏览器服务器模型

        服务器目标:

            处理速度快

            数据更安全

            并发量大

 

            硬件方面:

                更高的配置

                集成分布基础

                更好的网络速度

                更多主机

                更好的网络安全性

 

            软件方面:

                程序占有更少的资源

                更稳定的运行效果

                更流畅的运行速度

                采用更安全更合适的技术

 

    基础服务器模型

        循环服务器

            单进程程序,循环接收客户端请求,处理请求,每处理完一个请求再去接收下一个请求。

            优点:

                实现简单,占用资源少

            缺点:

                无法同时连接多个客户端,当一个客户端长期占有服务器时,形成其他客户端无法操作的情况

            使用情况:

                任务比较短暂,udp套接字更合适

        并发服务器

            同时处理多个客户端的任务请求

            io并发:io多路复用 协程

                优点:

                    资源消耗少,效率较高,适用于IO类型服务器

                缺点:

                    不能监控cpu密集型程序,本质是单进程所以不能长期阻塞消息的收发

            多进程、多线程并发

                为每一个客户端单独提供一个进程或者线程处理请求。由于进程线程执行独立所以对其他进程不会有影响

                优点:

                    客户端可以长期占有服务器,操作不会对其他进程现场产生影响

                缺点:

                    消耗资源较多

 

 

多进程并发

    使用 fork 完成并发

        1、创建套接字,绑定,监听

        2、等待接收客户端请求 accept

        3、创建子进程处理客户端请求

            父进程继续等待其他客户端连接

        4、客户端退出则子进程退出

 

多线程并发

    每有一个用户客户端就创建一个新的线程处理客户端请求

 

    对比多进程:

        优点:资源消耗少

        缺点:需要处理共享资源,注意GIL问题

 

    实现步骤

        1、创建套接字,绑定,监听

        2、接收客户端请求,创建新的线程

        3、主线程继续等待其他客户端连接,分支线程执行客户端请求

        4、处理完客户端请求后,分支线程退出,关闭客户端套接字

 

多进程并发的HTTPsever

    接收浏览器的http请求

    对请求进行解析

    根据解析判断请求内容

    将要返回的内容组织成http响应格式发送给客户端

 

    升级:

        使用多线程并发

        增加具体请求解析

        增加数据获取功能

        封装用类

    技术实现:

        threading 并发 tcp套接字

        tcp socket传输

        HTTP协议响应和请求的格式

 

socket 中的服务器的继承模块

    python2 SocketServer

    python3 socketserver

    功能:

        通过模块的接口完成基于多进程/多线程的tcp/udp的socket并发程序

    多进程tcp服务器

        from socketserver import *

        class Server(ForkingMixIn,TCPServer):

            pass

        class Handler(StreamRequestHandler):

            def handle(self):

                print(self.request.getpeername())

                while True:

                    data=self.request.recv(1024).decode()#接收消息

                    if not data:

                        break

                    print(data)

                    self.request.send(b'1111111')#发送消息

        server=Server(('0.0.0.0',8888),Handler)

        server.serve_forever()

 

    多进程udp服务

        from socketserver import*

        class Server(FokingUDPServer):

            pass

        class Handler(DatagramRequestHandler):

            def handle(self):

                while True:

                    data=self.rfile.readline().decode()#接收消息

                    if not data:

                        break

                    print(data)

                    self.wfile.write(b'11111111')#发送消息

        server=Server(('0.0.0.0',8888),Handler)

        server.serve_forever()

 

 

库的方法:

    sys.argv:

        功能:获取来自命令行的参数,形成一个列表,以空格作为每一项分隔,如果一项中有空格则用引号表示一个整体,命令行内容均作为字符串传入。

    format():合成字符串

    sys.stdin:输入

    sys.stdout:输出

    select.EPOLLET:边缘触发

    os.path.exists(path):

        功能:判断一个文件夹下是否有某个文件

    os.unlink(path) 或 os.remove(path):

        功能:删除一个文件

    获取文件大小

    os.path.getsize(path)

        功能:获取一个文件的大小

        参数:文件

    os.listdir(PATH):获取文件夹下的所有列表

    os.path.isfile(file):判断一个文件的类型是否为普通文件

    os.path.isdir(file):判断一个文件的类型是否为目录

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值