PYTHON2.day04

day23作业:

PYTHON2.day04
  1 from select import select
  2 from socket import *
  3 import sys
  4 from time import ctime
  5 
  6 s = socket()
  7 s.bind(('0.0.0.0',8888))
  8 s.listen(3)
  9 
 10 #监控
 11 rlist = [s,sys.stdin]#标准输入
 12 wlist = []
 13 xlist = []
 14 
 15 #日志文件
 16 f = open('log.txt','a')
 17 
 18 #训话监控
 19 while True:
 20     rs,ws,xs = select(rlist,wlist,xlist)
 21     for r in rs:
 22         if r is s:
 23             c,addr = r.accept()
 24             rlist.append(c)
 25         elif r is sys.stdin:
 26             f.write("%s %s"%(ctime(),r.readline()))#在终端度一行内容并写入
 27             f.flush()#刷新文件缓冲
 28         else:
 29             data = c.recv(1024)
 30             if not data:#如果客户端退出
 31                 rlist.remove()
 32                 r.close()
 33                 continue
 34             f.write("%s %s\n"%(ctime(),data.decode())) #在文件中追加当前时间...
 35 
select_test.pyPYTHON2.day04
  1 from socket import *
  2 
  3 #创套接字
  4 sockfd = socket()
  5 
  6 #发起连接
  7 server_addr = ('172.40.71.149',8888)
  8 sockfd.connect(server_addr)
  9 
 10 #收发消息
 11 while  True:
 12     #发
 13     data = input(">>")
 14     sockfd.send(data.encode())
 15     if not data:
 16         break
 17     #收
 18     # data = sockfd.recv(1024)
 19     # print("From server:",data.decode())
 20 
 21 #关闭套接子
 22 sockfd.close()
 23 
tcp_clent.pyPYTHON2.day04



一.基于poll方法的IO多路复用

1.select。poll()
   功能:创建poll对象
   返回值:poll
2.p.register(fd,event)
   功能:注册关注的IO事件
   参数:fd 要关注的IO
        event 要关注的IO事件类型
             * 常用类型:POLLIN 读IO事件 (rlist)
                         POLLOUT 写IO事件(wlist)
                         POLLERR 异常IO  (xlist)
                         POLLHUP 断开连接
            *e.g.  p.register(sockfd,POLLIN)#关注套接字的读事件
                    p.register(sockfd,POLLIN|POLLERR)#关注套接字的读事件
                    p.register(sockfd)#关注所有事件(尽量不用)

        p.unregister(fd)
         功能:取消对IO的关注
         参数:IO对象或者对象的frieno
        
*函数可以返回实例化对象

3.  enents = p.poll()#对象的方法
     功能:阻塞等待监控的IO事件发生
     返回值:返回发生的IO
             events格式 [(fileno,event),()...]
             每个元组为一个就绪IO,元组第一项是该IO的fileno,
             第二项为该IO的就绪的事件类型
            
     * 需要通过fileno寻找对应的IO对象,建立对应字典确保字典中IO和关注的IO时刻保持一致
       字典格式:{fileno:io_obj}
      
4.poll_server 步骤
   【1】创建套接字
   【2】将套接字register
   【3】创建查找字典,并维护
   【4】循环建监控IO发生
   【5】处理发生的IO
   

PYTHON2.day04
  1 from socket import *
  2 from select import *
  3 
  4 #创建要关注的IO
  5 s = socket()
  6 s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
  7 s.bind(('0.0.0.0',8888))
  8 s.listen(5)
  9 
 10 #创建poll对象
 11 p = poll()
 12 
 13 #建立查找字典
 14 fdmap = {s.fileno():s}
 15 
 16 #注册ID
 17 p.register(s,POLLIN|POLLERR)
 18 
 19 
 20 #循环监控
 21 while True:
 22     events = p.poll()#阻塞,返回列表
 23     #遍历列表,处理IO
 24     #元祖:fd文件描述符,event事件
 25     for fd,event in events:
 26 
 27         if fd ==s.fileno():#s就绪(监听套接字准备就绪)
 28             c,addr = fdmap[fd].accept()
 29             print("Connect from",addr)
 30             #添加新的注册ID
 31             p.register(c,POLLIN|POLLHUP)
 32             fdmap[c.fileno()] = c
 33 
 34         elif event & POLLHUP:
 35             print("客户端退出")
 36             p.unregister(fd)#取消关注
 37             fdmap[fd].close()
 38             del fdmap[fd]
 39 
 40         elif event & POLLIN:#真->pollin就绪;假-->poll未就绪
 41             data = fdmap[fd].recv(1024)
 42             print("Receive:",data.decode())
 43             fdmap[fd].send(b'Receive your msg')
 44 
poll_server.py

PYTHON2.day04
  1 from socket import *
  2 
  3 #创套接字
  4 sockfd = socket()
  5 
  6 #发起连接
  7 server_addr = ('172.40.71.149',8888)
  8 sockfd.connect(server_addr)
  9 
 10 #收发消息
 11 while  True:
 12     #发
 13     data = input(">>")
 14     sockfd.send(data.encode())
 15     if not data:
 16         break
 17     #收
 18     data = sockfd.recv(1024)
 19     print("From server:",data.decode())
 20 
 21 #关闭套接子
 22 sockfd.close()
 23 
tcp_cent.py

PYTHON2.day04
            
二.基于epoll方法的IO多路复用
     * 生成对象改为epoll()
     * 生成对象事件类型改为EPOLL类型
    
     epoll特点:
         *epoll 效率比select poll 要高
         *epoll(一直申请) 监控IO数量比select(1024)多
         *epoll的触发方式比poll要多(EPOLLET边缘触发)
      

PYTHON2.day04
  1 from socket import *
  2 from select import *
  3 
  4 #创建要关注的IO
  5 s = socket()
  6 s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
  7 s.bind(('0.0.0.0',8888))
  8 s.listen(5)
  9 
 10 #创建poll对象
 11 p = epoll()
 12 
 13 #建立查找字典
 14 fdmap = {s.fileno():s}
 15 
 16 #注册ID
 17 p.register(s,EPOLLIN|EPOLLERR)
 18 
 19 
 20 #循环监控
 21 while True:
 22     events = p.poll()#阻塞,返回列表
 23     #遍历列表,处理IO
 24     #元祖:fd文件描述符,event事件
 25     for fd,event in events:
 26 
 27         if fd ==s.fileno():#s就绪(监听套接字准备就绪)
 28             c,addr = fdmap[fd].accept()
 29             print("Connect from",addr)
 30             #添加新的注册ID
 31             p.register(c,EPOLLIN|EPOLLHUP)
 32             fdmap[c.fileno()] = c
 33 
 34         elif event & EPOLLHUP:
 35             print("客户端退出")
 36             p.unregister(fd)#取消关注
 37             fdmap[fd].close()
 38             del fdmap[fd]
 39 
 40         elif event & EPOLLIN:#真->pollin就绪;假-->poll未就绪
 41             data = fdmap[fd].recv(1024)
 42             print("Receive:",data.decode())
 43             fdmap[fd].send(b'Receive your msg')
 44 
 45 
 46 
epoll_server.py

PYTHON2.day04
  1 from socket import *
  2 
  3 #创套接字
  4 sockfd = socket()
  5 
  6 #发起连接
  7 server_addr = ('172.40.71.149',8888)
  8 sockfd.connect(server_addr)
  9 
 10 #收发消息
 11 while  True:
 12     #发
 13     data = input(">>")
 14     sockfd.send(data.encode())
 15     if not data:
 16         break
 17     #收
 18     data = sockfd.recv(1024)
 19     print("From server:",data.decode())
 20 
 21 #关闭套接子
 22 sockfd.close()
 23 
tcp_clent.py

PYTHON2.day04 
三.struct模块的使用
1.原理:将一组金丹数据进行打包,转换为bytes格式发送。或者将一组bytes格式数据,进行解析。
2.接口使用
   [1] Struct(fmt)
       功能:生成结构化对象
       参数:fmt 定制了数据结构
       e.g. 要发送数据 1 b'zhangsan'  1.75
            fmt参数     "i8sf"(8个字串)
  [2]st.pack(v1,v2,v3...)
      功能:将一组数据按照指定格式打包转换为bytes
      参数:要打包的数据
      返回值:bytes字节串
   [3]st.unpack(bytes)
       功能:将bytes字节串按照指定的格式解析
       参数:要解析的字符串
       返回值:解析后的内容
  [4]struct.pack(fmt,v1,v2,v3...)
      struct.unpack(fmt,bytes_data)

      说明:可以使用struct模块直接调用pack unpack
            此时这两个参数传入fmd,其他用发功能相同
   

PYTHON2.day04
  1 from socket import *
  2 import struct
  3 
  4 s = socket(AF_INET,SOCK_DGRAM)
  5 s.bind(('0.0.0.0',8888))
  6 
  7 #确定数据结构
  8 st = struct.Struct('i16sf')
  9 
 10 while True:
 11     data,addr = s.recvfrom(1024)
 12     #解析
 13     data = st.unpack(data)
 14     print(data)
 15 
 16 s.close()
struct_receive.py

PYTHON2.day04
  1 from socket import *
  2 import struct
  3 
  4 ADDR = ('172.40.71.149',8888)
  5 s = socket(AF_INET,SOCK_DGRAM)
  6 
  7 while True:
  8     my_id = int(input("id:"))
  9     name = input("name:")
 10     height = float(input("height:"))
 11     # len = len(name)
 12 
 13     fmt = "i16sf"
 14     data = struct.pack(fmt,my_id,name.encode(),height)
 15     s.sendto(data,ADDR)
 16 
 17 s.close()
struct_clent.py

PYTHON2.day04       
     
四.本地套接字
     1.功能:用于本地的两个程序之间进行数据的收发
     2.套接字文件:用于本地套接字之间通信时,进行数据传输的介质。
     3.创建本地套接字的流程
       【1】创建本地套接字
            socket = sorted(AF_UNIX,SOCK_STREEAM)
       【2】绑定本地套接字文件
            sockfd.bind(file)
       【3】监听,接收客户端连接,消息收发
            listen()-->accept()-->recv(),send()
     
     cookie:Linux下文件类型
         b(块设备文件)     
         c(字符设备文件)  
         d(目录)
         -(普通文件)    
         l(连接文件)   
         s(套接字文件)       
         p(管道文件)
        

PYTHON2.day04
  1 from socket import *
  2 import os
  3 
  4 #确定套接字文件
  5 sock_file = './sock'
  6 
  7 #判断文件是否存在,存在就删除
  8 if os.path.exists(sock_file):
  9     os.remove(sock_file)
 10 
 11 
 12 #创建本地套接字
 13 sockfd = socket(AF_UNIX,SOCK_STREAM)
 14 
 15 #绑定套接字文件
 16 sockfd.bind(sock_file)
 17 
 18 #监听,连接
 19 sockfd.listen(3)
 20 while True:
 21     c,addr = sockfd.accept()
 22     while True:
 23         data = c.recv(1024)
 24         if not data:
 25             break
 26         print(data.decode())
 27     c.close()
 28 sockfd.close()
unix_receive.py

PYTHON2.day04
  1 from socket import *
  2 
  3 #确保两边使用同一个套接字文件
  4 sock_file = './sock'
  5 sockfd = socket(AF_UNIX,SOCK_STREAM)
  6 sockfd.connect(sock_file)
  7 
  8 while True:
  9     msg = input(">>")
 10     if not msg:
 11         break
 12     sockfd.send(msg.encode())
 13 
 14 sockfd.close()
unix_send.py

PYTHON2.day04
    
五.多任务编程
     1.意义:充分利用计算机多核咨询,提高程序的运行效率
     2.实现方案:多进程 ,多线程
     3.并行,并发概念
       * 并发:同时处理多个任务,内核咋任务间不断切换达到多个任务被同时执行的效果,
               实际每个时刻只有一个任务占有内核
       * 并行:多个任务利用计算机多核资源在同时执行,此时多个任务间同时为并行关系。
      
      
六.进程(process)
    1.定义:程序在计算机中的一次运行
      * 程序是一个可执行的文件是静态的占有磁盘
      * 进程是一个动态的过程描述,占有计算机运行资源,有一定的生命周期
     
    2. 如何产生一个进程
       【1】用户空间通过调用程序接口命令发起请求
       【2】操作系统接收用户请求,开始创建进程
       【3】操作系统调配计算机资源,确定进程状态等
       【4】操作系统将创建的进程提供给用户使用
    3.进程概念
        * cpu时间片:如果一个进程占有cpu内核则称这个进程在cpu时间片上
        *PCB(进程控制块):在内存中开辟的一块空间,用于存放进程的基本信息,
             也用于系统查找识别进程
        *进程ID(PID):系统为每个进程分配的一个大于0 的整数,作为进程ID,每个ID不会重复。
       
        Linux查看进程ID:ps -aux
        PYTHON2.day04
        * 父子进程:系统中每一个进程(除了系统初始化进程)
         都有唯一的父进程,可以有0个或多个子进程。父子进程关系便于进程管理
        
         查看进程树:pstree

PYTHON2.day04
         *进程状态
              三态:
                  就绪态:进程具备执行条件。等待分配cup资源
                  运行态:进程占有cpu时间片正在运行
                  等待态:进程暂停时停止运行。
              五态:
                  新建:创建一个进程,获取资源的过程
                  终止:进程结束,释放资源的过程
                 
             状态查看命令:ps -aux --->STAT列
            
             S 等待态
             R 执行态
             D 等待态
             T 等待态
             Z 僵尸     
      
             < 有较高优先级
             N 优先级较低
             + 前台进程
             s 会话组组长
             l 有多线程的
            
            

面试要求:1.什么是进程,进程和程序有什么区别
           2.进程有哪些状态,状态之间如何转化
          
作业:1.对要求问题总结回答
       2.整理网络编程重点程序
       能够自己写出 tcp服务器 udp服务端  select服务端  poll服务端

上一篇:TCP/UDP套接字网络协议


下一篇:如何用C语言写一个基于服务器和客户端(TCP)