zoukankan      html  css  js  c++  java
  • 网络编程(三)

    前情回顾
    缓冲区
    粘包 tcp
    udp通信 recvfrom sendto
    广播
    http协议
    文件传输
    ***********************************************
    tcp应用 http服务器
    1.接收http请求
    2.给出一定的响应

    IO input output
    在内存中存在数据交换的操作
    内存和磁盘交换 文件读写 打印
    内存和网络交换 recv send

    IO密集型程序 : 程序执行中执行大量的IO操作,而较少需要cpu运算 消耗cpu资源少,运行周期往往较长

    cpu密集型程序: 程序执行中需要大量的cpu运算,IO操作较少。占用cpu多

    IO分类
    阻塞IO :默认形态 是效率最低的一种IO
    阻塞 : 因为等待某种条件达成再继续运行
    例如 accept recv input

    处理IO事件的时候耗时较长也会产生阻塞
    例如 文件的读写过程,网络数据的传输过程

    非阻塞IO : 通过修改IO对象使其变为非阻塞状态(改变第一种阻塞形态)

    通常用循环不断判断阻塞条件,需要消耗更多cpu但是一定程度上提高了IO效率


    s.setblocking()
    功能 : 将套接字设置的阻塞状态
    参数 : bool 默认为True 设置为False则为非阻塞

    超时等待(检测)

    cookie

    更专业的打印异常信息
    import traceback
    trancback.print_exc()

    s.settimeout()
    功能 : 设置套接字的超时监测
    参数 : 超时时间

    所谓超时监测即 对原本阻塞的函数进行设置,使其不再始终阻塞,而是阻塞等待一定时间后自动返回。在规定时间中如果正常结束阻塞则继续执行否则产生timeout异常
    select join() wait

    IO多路复用

    定义 : 同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件,形成并发的效果

    import select

    select ------》 win linux unix
    poll -----》 linux、unix
    epoll

    r,w,x = select(rlist,wlist,xlist,[timeout])
    功能 :监控IO事件,阻塞等待IO事件发生
    参数 :rlist 列表 存放我们要监控等待处理的IO

    wlist 列表 存放我们希望主动处理的IO

    xlist 列表 存放如果发生异常需要我们处理的

    timeout 数字 超时监测 默认一直阻塞

    返回值 : r 列表 rlist当中准备就绪的IO
    w 列表 wlist当中准备就绪的IO
    x 列表 xlist当中准备就绪的IO

    IO多路复用注意点:
    1. 在处理io过程中不应发生死循环(某个IO单独占有服务器)
    2. io多路复用是单进程程序,是一个并发程序
    3. io多路复用有较高的IO 执行效率


    poll

    1. 创建poll对象
    p = select.poll()

    2. 加入关注的IO
    p.register(s)
    p.unregister(s) 从关注IO中删除

    3. 使用poll函数监控
    events = p.poll()
    功能 : 阻塞等待register的事件只要有任意准备就绪即返回
    返回值:events [(fileno,event),(),()]

    4. 处理发生的IO事件

    poll io事件
    POLLIN POLLOUT POLLUP POLLERR POLLPRI POLLVAL
    rlist wlist 断开连接 xlist 紧急处理 无效数据

    s & POLLIN


    epoll

    * 效率上比poll和select稍微高
    * 只能用于linux unix
    * 支持边缘触发 select poll只支持水平触发


    作业 :
    复习tcp udp select三个代码能够自己完成


    下面是关于python的程序:
    ********************************************************
    (1)timeout_server.py

    from socket import *
    from time import sleep,ctime
    import traceback

    s = socket()
    s.bind(('127.0.0.1',8888))
    s.listen(5)
    #设置s超时检测
    s.settimeout(5)

    while True:
    print("waiting for connect....")
    try:
    connfd,addr = s.accept()
    except Exception:
    traceback.print_exc()
    continue

    print("connect from",addr)
    # recv设置超时
    # connfd.settimeout(3)
    while True:
    data = connfd.recv(1024)
    if not data:
    break
    print(data.decode())
    connfd.send('来,确认下眼神'.encode())
    connfd.close()
    s.close()
    ********************************************************
    (2)recv_file.py

    from socket import *
    s = socket()
    s.connect(("127.0.0.1",8888))
    f = open('recv_file','w')
    while True:
    data = s.recv(1024).decode()
    if data == '##':
    break
    f.write(data)
    f.close()
    s.close()

    send_file.py

    from socket import *
    from time import sleep

    s = socket()
    s.bind(("127.0.0.1",8888))
    s.listen(5)

    c,addr = s.accept()
    print("Connect from ",addr)

    f = open('send_file','rb')

    while True:
    data = f.read(128)
    if not data:
    sleep(0.5)
    c.send(b'##')
    break
    c.send(data)
    f.close()
    c.close()
    s.close()
    ********************************************************
    (3)block_server.py

    from socket import *
    from time import sleep,ctime

    s = socket()
    s.bind(('127.0.0.1',8888))
    s.listen(5)
    #设置s是非阻塞状态
    s.setblocking(False)
    while True:
    print("waiting for connect....")
    try:
    connfd,addr = s.accept()
    except BlockingIOError:
    sleep(2)
    print(ctime())
    continue

    print("connect from",addr)
    # recv变为非阻塞
    # connfd.setblocking(False)
    while True:
    data = connfd.recv(1024)
    if not data:
    break
    print(data.decode())
    connfd.send('来,确认下眼神'.encode())
    connfd.close()
    s.close()
    ********************************************************
    (4)select_server.py

    from socket import *
    from select import *
    import sys

    s = socket()
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(("127.0.0.1",8888))
    s.listen(10)

    #将关注的IO放入rlist
    rlist = [s]
    wlist = []
    xlist = [s]

    while True:
    print("等待IO")
    #wlist中有内容select会立即返回
    rs,ws,xs = select(rlist,wlist,xlist,3)
    for r in rs:
    #表示套接字准备就绪
    if r is s:
    connfd,addr = r.accept()
    print("Connect from",addr)
    #将新的套接字加入到关注列表
    rlist.append(connfd)
    else:
    try:
    data = r.recv(1024)
    if not data:
    rlist.remove(r)
    r.close()
    else:
    print("Received from",r.getpeername(),
    ":",data.decode())
    #想发消息可以放到写关注列表
    wlist.append(r)
    except Exception:
    pass

    for w in ws:
    w.send("天地悠悠,一壶浊酒".encode())
    wlist.remove(w)

    for x in xs:
    if x is s:
    s.close()
    sys.exit(1)
    ********************************************************
    (5)poll_server.py

    from socket import *
    from select import *
    import sys

    s = socket()
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(("0.0.0.0",8888))
    s.listen(10)

    #创建IO事件地图
    fdmap = {s.fileno():s}
    #创建poll对象
    p = poll()
    #将套接字加入到关注
    p.register(s,(POLLIN | POLLERR))

    while True:
    #进行监控
    events = p.poll()
    # print(events)
    for fd,event in events:
    if fd == s.fileno():
    c,addr = fdmap[fd].accept()
    print("connect from",addr)
    p.register(c,POLLIN)
    fdmap[c.fileno()] = c
    elif event & POLLIN:
    data = fdmap[fd].recv(1024)
    if not data:
    p.unregister(fd)
    fdmap[fd].close()
    del fdmap[fd]
    else:
    print(data.decode())
    fdmap[fd].send("收到了".encode())
    ********************************************************
    (6)Httpserver.py

    #静态网页处理器
    #采用循环的模式,无法满足客户端长连接

    from socket import *

    #处理客户端请求
    def handleClient(connfd):
    request = connfd.recv(2048)
    requestHeadlers = request.splitlines()
    for line in requestHeadlers:
    print(line)

    try:
    f = open("知乎.html",'r')
    except IOError:
    response = "HTTP/1.1 404 not found "
    response += ' '
    response += "====sorry ,file not find"
    else:
    response = "HTTP/1.1 200 OK "
    response += ' '
    for i in f:
    response += i
    finally:
    connfd.send(response.encode())
    connfd.close()

    #流程控制
    def main():
    sockfd = socket()
    sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    sockfd.bind(('0.0.0.0',8000))
    sockfd.listen(10)
    while True:
    connfd,addr = sockfd.accept()
    handleClient(connfd)


    if __name__ == "__main__":
    main()
    ********************************************************
  • 相关阅读:
    VBA的程序终止、退出语句块、分支及错误处理(End, exit, on error go to in VBA
    关于session中的cookie提取
    Python爬虫 —— 知乎之selenium模拟登陆获取cookies+requests.Session()访问+session序列化-转
    tar 解压命令出现如下错误
    操作系统 ----- 段错误(核心转储)
    c++游戏入门基础
    数据结构算法
    point(指针)
    《淘宝网》质量属性简析
    《架构漫谈》读后感
  • 原文地址:https://www.cnblogs.com/wcin/p/9113923.html
Copyright © 2011-2022 走看看