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

    内核 ----》操作系统的核心代码

    并发 : 同时处理多个请求,但是内核采用轮询时间片的方式逐个访问,某一时间点实际只处理一个任务。

    比如 :IO多路复用 协程 循环服务器。单线程

    并行 : 使用多个内核,同时执行多个任务

    比如 : 多进程 多线程


    计算机原理 算法导论
    python程序员 python开发者
    掘金

    线程 threading.Thread

    进程和线程的同步互斥
    Event Lock

    **********************************************
    condition 条件变量

    创建条件变量对象
    con = threading.Condition()

    con.acquire() : 对资源加锁,加锁后其他位置再加锁则阻塞
    con.release() : 解锁

    con.wait() : wait函数只能在 加锁的状态下使用。 wait函数会先解锁(release),然后让线程处于等待通知的阻塞状态

    con.notify() : 发送通知,线程接收到通知后 结束wait阻塞,并且执行 acquire 加锁操作


    threadpool 第三方模块

    python线程之GIL
    (全局解释器锁)
    python ---》 支持多线程 ---》同步互斥 ---》加锁 ---》 超级锁 ----》 在同一时刻,解释器只能解释一个线程 -----》大量python库为了省事沿用了这种方法 ---》python 多线程效率低下

    GIL 问题 : 由于python的全局解释器锁造成python的多线程执行效率低下

    解决方法 :
    * 不使用线程,使用多进程
    * 不使用c c++ 做解释器 C# java
    * python线程适合高用时的IO操作,网路IO。不适合cpu密集型程序

    GIL带来的影响
    单进程
    Line cpu: 6.7326600551605225
    Line IO: 3.783463478088379

    多线程
    Thread cpu 6.855324745178223
    Thread IO 4.32829213142395

    多进程
    Process cpu 3.297400951385498
    Process IO 1.6371185779571533


    设计模式

    设计模式代表了一种最佳实践,是被开发人员长期总结,用来解决某一类问题的思路方法。这些方法保证了代码的效率也已于理解

    单例模式 工厂模式 生产者模式。。。。

    生产者消费者

    控制数据资源数量
    降低耦合度

    多个消费者 消耗
    多个生产者 生产
    均对仓库资源进行操作

    总结:
    1. 进程线程区别和联系
    2. 同步互斥的意义和实现方法
    3. 进程线程使用什么样的方式通信
    4. 进程线程的特点和选择
    5. 简单的设计模式的理解
    6. 僵尸进程,进程状态, GIL等概念的理解


    服务器模型

    硬件服务器 : 主机 集群
    IBM HP

    软件服务器 : 网络服务器 在后端提供网络功能,逻辑处理,数据处理的程序或者架构等
    例如 httpserver django flask

    服务器架构 : c/s(客户端服务器)
    b/s(浏览器服务器)
    服务器的组织形式

    服务器追求 : 处理速度快,数据更安全,并发量大

    硬件 : 更高配置,更多主机,集成,分布
    软件 : 程序占有更少的资源,更流畅的运行,处理更多的并发

    基本的服务器模型

    循环 并发模式 IO多路复用

    循环 : 单线程程序 ,循环接收连接或者请求,然后处理,处理后继续循环

    缺点 : 不能同时处理多个客户端的并行,不允许某个客户端长期占有服务器

    结构比较简单,适用于UDP程序,要求处理请求可以很快完成

    IO多路复用模型:通过同时监控多个IO 来达到IO并发的目的。

    缺点 : 也是单线程,不能够长期阻塞。不适合处理大量cpu占有高的程序

    开销小,比较适合IO密集型的服务端程序,

    并行服务器: 每有一个客户端连接请求,就创建一个新的进程或者线程处理客户端的请求,而主进程/主线程可以继续接受其他客户端的连接

    缺点 : 资源消耗比较大
    客户端需要长期占有服务器的情况

    基于fork的多进程并发

    1.创建套接字 绑定 监听
    2.接受客户端请求
    3.创建子进程处理客户端请求,父进程继续准备接受新的客户端连接
    4.客户端退出,销毁相应的子进程

    TFTP文件服务器

    文件的上传,下载,和服务端文件库的查看

    服务端 客户端
    1.查看文件库中有哪些文件
    2.下载文件到本地

    确定技术

    fork --- 多进程
    tcp socket

    os.listdir(path)
    获取该文件夹下所有文件,形成一个列表

    os.path.isfile(path)
    os.path.isdir(path)
    判断一个文件是否是普通文件/文件夹

    作业 : 完成tftp文件服务器 get 和 put功能

    **********************************************************************
    import threading
    import time
    import datetime

    num = 0

    #条件变量
    con = threading.Condition()

    class Gov(threading.Thread):
    def run(self):
    global num
    con.acquire()
    while True:
    print("开始拉升股市")
    num += 1
    print("拉升到 %d 个点"%num)
    time.sleep(2)
    if num == 5:
    print('暂时安全!')
    con.notify()
    print("不操作状态")
    con.wait()
    con.release()

    class Consumers(threading.Thread):
    def run(self):
    global num
    con.acquire()
    while True:
    if num > 0:
    print("开始打压股市")
    num -= 1
    print("下降到%d个点"%num)
    time.sleep(2)
    if num == 0:
    print("天台在哪")
    con.notify()
    print("不能在下降了")
    con.wait()
    con.release()

    t1 = Gov()
    t2 = Consumers()
    t1.start()
    t2.start()

    **********************************************************************************
    import multiprocessing as mp
    from signal import *
    import os
    from time import sleep

    def saler_handler(sig,frame):
    if sig == SIGINT:
    os.kill(os.getppid(),SIGUSR1)
    elif sig == SIGQUIT:
    os.kill(os.getppid(),SIGUSR2)
    elif sig == SIGUSR1:
    print("到站了,请下车")
    os._exit(0)

    def driver_handler(sig,frame):
    if sig == SIGUSR1:
    print("老司机,开车了")
    elif sig == SIGUSR2:
    print("车速有点快,系好安全带")
    elif sig == SIGTSTP:
    os.kill(p.pid,SIGUSR1)

    #售票员
    def saler():
    signal(SIGINT,saler_handler)
    signal(SIGQUIT,saler_handler)
    signal(SIGUSR1,saler_handler)
    signal(SIGTSTP,SIG_IGN)
    while True:
    sleep(2)
    print("Python 带你去远方")

    p = mp.Process(target = saler)
    p.start()

    signal(SIGUSR1,driver_handler)
    signal(SIGUSR2,driver_handler)
    signal(SIGTSTP,driver_handler)
    signal(SIGINT,SIG_IGN)
    signal(SIGQUIT,SIG_IGN)
    p.join()

    **********************************************************************************
    from socket import *
    import os,sys
    import signal

    #创建套接字
    HOST = ""
    PORT = 8888

    def client_handler(c):
    try:
    print("子进程接受客户的请求",c.getpeername())
    while True:
    data = c.recv(1024).decode()
    if not data:
    break
    print(data)
    c.send(b"receive your message")
    except (KeyboardInterrupt,SystemExit):
    raise
    except Exception as e:
    print(e)
    c.close()
    sys.exit(0) # 结束子进程

    s = socket()
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind((HOST,PORT))
    s.listen(5)

    print("父进程 %d 等待客户端链接"%os.getpid())
    while True:
    try:
    c,addr = s.accept()
    except KeyboardInterrupt:
    raise
    except Exception as e:
    print(e)
    continue
    #为新的客户端创建进程

    #处理僵尸进程
    signal.signal(signal.SIGCHLD,signal.SIG_IGN)

    pid = os.fork()
    if pid < 0:
    print("创建子进程失败")
    c.close()
    continue
    elif pid == 0:
    s.close()
    #处理客户端请求
    client_handler(c)
    else:
    c.close()
    continue

    **********************************************************************************
    from threading import Thread
    #python标准库队列
    import queue
    from time import sleep

    #创建一个队列作为仓库
    q = queue.Queue()

    #生产者
    class Producer(Thread):
    def run(self):
    count = 0
    while True:
    if q.qsize() < 50:
    for i in range(3):
    count += 1
    msg = "产品 %d"%count
    q.put(msg) #将产品放入队列
    sleep(1)

    #消费者
    class Customer(Thread):
    def run(self):
    while True:
    if q.qsize() > 20:
    for i in range(2):
    msg = q.get() #从仓库拿货
    print("消费了%s"%msg,
    "还有%d个"%q.qsize())
    sleep(1)
    #创建两个生产
    for i in range(2):
    p = Producer()
    p.start()
    #创建三个消费
    for i in range(3):
    c = Customer()
    c.start()

    **********************************************************************************
    from socket import *
    import sys
    import time

    #客户请求类
    class TftpClient(object):
    def __init__(self,sockfd):
    self.sockfd = sockfd

    def do_list(self):
    self.sockfd.send(b'L') #发送请求类别

    #服务器回复 Y / N
    data = self.sockfd.recv(1024).decode()
    if data == 'Y':
    data = self.sockfd.recv(4096).decode()
    files = data.split('#')
    for file in files:
    print(file)
    print("文件列表展示完毕")
    else:
    print("请求文件列表失败")

    def do_get(self,filename):
    pass
    def do_put(self,filename):
    pass
    def do_quit(self):
    self.sockfd.send(b"Q")
    self.sockfd.close()
    sys.exit(0)

    def main():
    if len(sys.argv) < 3:
    print("argv is error")
    sys.exit(1)
    HOST = sys.argv[1]
    PORT = int(sys.argv[2])
    ADDR = (HOST,PORT)
    BUFFERSIZE = 1024
    sockfd = socket()
    sockfd.connect(ADDR)

    #创建客户请求对象
    tftp = TftpClient(sockfd)

    while True:
    print("========命令选项========")
    print("******** list **********")
    print("******* get file *******")
    print("******* put file *******")
    print("******** quit **********")
    print("========================")
    data = input("输入命令>>")
    if data.strip() == "list":
    tftp.do_list()
    elif data[:3] == "get":
    filename = data.split(' ')[-1]
    tftp.do_get(filename)
    elif data[:3] == "put":
    filename = data.split(' ')[-1]
    tftp.do_put(filename)
    elif data.strip() == "quit":
    tftp.do_quit()
    else:
    print("请输入正确的命令!!!")

    if __name__ == "__main__":
    main()

    **********************************************************************************
    from socket import *
    import os,sys
    import signal
    import time

    #文件库位置
    FILE_PATH = "/home/tarena/pythonweb/day3/"

    class TftpServer(object):
    def __init__(self,connfd):
    self.connfd = connfd

    def do_list(self):
    filelist = os.listdir(FILE_PATH)
    if not filelist:
    self.connfd.send(b'N')
    return
    else:
    self.connfd.send(b"Y")
    time.sleep(0.1)
    files = ""
    for filename in filelist:
    if filename[0] != '.' and os.path.isfile(FILE_PATH + filename):
    files = files + filename + '#'

    self.connfd.send(files.encode())

    def do_get(self):
    pass
    def do_put(self):
    pass

    def main():
    if len(sys.argv) < 3:
    print("argv is error")
    sys.exit(1)
    HOST = sys.argv[1]
    PORT = int(sys.argv[2])
    ADDR = (HOST,PORT)
    BUFFERSIZE = 1024

    sockfd = socket()
    sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    sockfd.bind(ADDR)
    sockfd.listen(5)
    signal.signal(signal.SIGCHLD,signal.SIG_IGN)

    while True:
    try:
    connfd,addr = sockfd.accept()
    except KeyboardInterrupt:
    sockfd.close()
    sys.exit(0)
    except Exception:
    continue
    print("客户登录:",addr)
    pid = os.fork()
    if pid < 0:
    print("创建子进程失败")
    connfd.close()
    continue
    elif pid == 0:
    sockfd.close()
    #创建客户端通信对象
    tftp = TftpServer(connfd)
    while True:
    #接受客户端的请求类型
    data = connfd.recv(BUFFERSIZE).decode()
    if data[0] == 'L':
    tftp.do_list()
    elif data[0] == 'G':
    tftp.do_get()
    elif data[0] == "P":
    tftp.do_put()
    elif data[0] == "Q":
    print("客户端退出")
    sys.exit(0)
    else:
    connfd.close()
    continue

    if __name__ == "__main__":
    main()
    **********************************************************************************
  • 相关阅读:
    [再寄小读者之数学篇](2014-06-19 满足三个积分等式的函数)
    [再寄小读者之数学篇](2014-06-19 微分等式的结论)
    我的一些武功
    TEX学习笔记
    我的一些诗词
    我的课程与学生
    [再寄小读者之数学篇](2014-06-19 三维插值公式)
    [再寄小读者之数学篇](2014-06-19 旋度公式)
    JAVA小项目实例源码—学习娱乐小助手
    可拖拽的3D盒子
  • 原文地址:https://www.cnblogs.com/wcin/p/9119227.html
Copyright © 2011-2022 走看看