美文网首页
服务器模型

服务器模型

作者: 遇明不散 | 来源:发表于2019-04-20 20:04 被阅读0次

    服务器

    硬件服务器

    计算机主机

    软件服务器
    • 网络服务器,提供后端逻辑服务和请求处理的程序集合及架构
    • 编写的服务端应用程序,在硬件服务器上运行,一般依托于操作系统,给用户提供一套完整的服务
    服务器架构

    服务器的组织形式
    c/s 客户端服务器模型
    b/s 浏览器服务器模型

    服务器目标
    • 处理速度更快,并发量更高,安全性更强
    • 硬件:更高的配置,更好的集成分布技术,更好的网络优 化和网络安全技术
    • 软件:占用资源更少,运行更稳定,算法更优良,安全性 更好,并发性更高,更容易扩展
    常见服务器
    • httpserver:处理http请求
    • webserver:网站的后端应用服务器程序
    • 邮箱服务器:邮件处理
    • ftp文件服务器:文件的上传下载
      功能:网络连接,逻辑处理,数据交互,数据传输,协议的实现

    服务器模型

    循环服务器模型
    • 循环接收客户端请求,处理请求。同一时刻只能处理一个请求,处理完毕后再处理下一个
    • 实现简单,占用资源少
    • 不能同时处理多个客户端请求,不允许某个客户端长期占用服务器资源
    • 由于UDP不需要进行连接,所以循环服务器模型更加适合UDP通信
    并发服务器模型

    能够同时处理多个客户端请求,每有一个客户端就创建一个进程或线程处理客户端的具体请求事件,而主进程或主线程继续接受其他客户端的连接

    IO并发(IO多路复用)
    • 优点:资源消耗少,IO处理速度快
    • 缺点:不能适用cpu密集型程序
    多进程/多线程并发
    • 为每个客户端创建单独的进程线程,执行请求
    • 优点:每个客户端可以长期占有服务器运行程序,能够使用多核资源,可以处理IO或者cpu运算
    • 缺点:消耗系统资源高

    多进程并发服务器模型

    使用fork实现多进程并发
    • 创建套接字,绑定,监听
    • 主进程等待接收客户端请求
    • 创建新的子进程处理客户端请求
    • 原有主进程继续等待接收新的客户端连接
    • 如果客户端退出则关闭子进程
    # fork_server.py
    from socket import *
    import sys
    import signal
    import os
    
    # 主机地址与端口
    HOST = '127.0.0.1'
    PORT = 8888
    ADDR = (HOST,PORT)
    
    # 主进程忽略子进程的退出,子进程退出自动由系统处理
    signal.signal(signal.SIGCHLD,signal.SIG_IGN)
    
    # 客户端处理函数
    def client_handler(c):
        print('服务器已连接到客户端:',c.getpeername())
        try:
            while True:
                data = c.recv(1024)
                if not data:
                    break
                print('%s说:%s'%(c.getpeername(),data.decode()))
                c.send('收到客户端请求'.encode())
        except (KeyboardInterrupt,SystemError):
            sys.exit('客户端退出')
        except Exception as e:
            print('服务器内部错误信息:',e)
        c.close()
        sys.exit(0)
    
    # 创建套接字
    s = socket(AF_INET,SOCK_STREAM,0)
    # 设置端口可重用
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    # 绑定
    s.bind(ADDR)
    # 监听
    s.listen(5)
    # 主进程等待接收客户端请求
    print('进程%d正在等待接受请求:'%os.getpid())
    while True:
        try:
            c,addr = s.accept()
        except KeyboardInterrupt:
            sys.exit('服务器退出,暂无服务可连')
        except Exception as e:
            print('错误信息:',e)
            continue
        # 创建新的子进程处理客户端请求
        pid = os.fork()
        # 判断是否是子进程
        if pid == 0:
            s.close()
            client_handler(c)
        # 如果不是子进程或者创建失败,则继续等待接受其他客户端
        else:
            c.close()
            continue
    
    使用multiprocessing模块实现多进程并发
    from socket import * 
    import os,sys 
    from multiprocessing import Process
    import traceback 
    
    def handler():
        print("Connect from",c.getpeername())
        while True:
            data = c.recv(1024).decode()
            if not data:
                break 
            print(data)
            c.send(b'Receive request')
        c.close()
    
    s = socket()
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(('0.0.0.0',8899))
    s.listen(5)
    while True:
        try:
            c,addr = s.accept()
        except KeyboardInterrupt:
            s.close()
            sys.exit("服务器退出")
        except Exception:
            traceback.print_exc()
            continue 
        t = Process(target = handler)
        t.daemon = True
        t.start()
    

    多线程并发服务器模型

    对比多进程并发
    • 消耗资源较少
    • 线程应该更注意共享资源的操作
    • 在python中应该注意GIL问题,网络延迟较高,线程并发也是一种可行的办法
    实现步骤
    • 创建套接字,绑定监听
    • 接收客户端请求,创建新的线程
    • 主线程继续接收其他客户端连接
    • 分支线程启动对应的函数处理客户端请求
    • 当客户端断开,则分支线程结束
    from socket import * 
    import os,sys 
    from threading import *
    import traceback 
    
    def handler(c):
        print("Connect from",c.getpeername())
        while True:
            data = c.recv(1024).decode()
            if not data:
                break 
            print(data)
            c.send(b'Receive request')
        c.close()
    
    s = socket()
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(('0.0.0.0',8899)) 
    s.listen(5)
    while True:
        try:
            c,addr = s.accept()
        except KeyboardInterrupt:
            s.close()
            sys.exit("服务器退出")
        except Exception:
            traceback.print_exc()
            continue 
        t = Thread(target = handler,args = (c,))
        t.daemon = True
        t.start()
    

    补充

    import os
    # 获取目录中文件列表
    os.listdir(path)  
    # 判断是否为普通文件
    os.path.isfile()  
    # 判断是否为目录
    os.path.isdir()  
    
    import traceback
    # 更详细的打印异常信息
    traceback.print_exc()
    

    集成模块socketserver

    通过模块的不同类的组合完成多进程/多线程的TCP/UDP的并发

    套接字请求

    StreamRequestHandler 处理tcp套接字请求
    DatagramRequestHandler 处理udp套接字请求

    创建套接字

    TCPServer 创建tcp server
    UDPServer 创建udp server

    创建多进程

    ForkingMixIn
    ForkingTCPServer <--> ForkingMinIn + TCPServer
    ForkingUDPServer <--> ForkingMinIn + UDPServer

    创建多线程

    ThreadingMixIn
    ThreadingTCPServer <--> ThreadingMinIn + TCPServer
    ThreadingUDPServer <--> ThreadingMinIn + UDPServer

    步骤
    • 创建服务器类
    • 创建处理类
    • 使用创建的服务器类来产生服务器

    相关文章

      网友评论

          本文标题:服务器模型

          本文链接:https://www.haomeiwen.com/subject/nbkcgqtx.html