服务器模型

服务器

硬件服务器

计算机主机

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

服务器的组织形式
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

步骤
  • 创建服务器类
  • 创建处理类
  • 使用创建的服务器类来产生服务器
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,142评论 1 32
  • 第一章 引言和网络编程基础知识 1.1 分别简述OSI参考模型和TCP/IP模型,并阐述他们之间的对应关系 1.2...
    V0W阅读 5,402评论 0 9
  • 目前常见的服务器模型主要有三种:阻塞服务器,并发服务器以及异步服务器。三种形式各有利弊,下面介绍一下。 第一种阻塞...
    onlyHalfSoul阅读 2,020评论 0 1
  • 我们遍寻世界,期望看到闪光的人和事物,正是他们/她们一遍遍告诫和提醒我们:世界有好多形状,人生有好多可能,活着有许...
    云妮yunni阅读 286评论 0 2
  • 我去街上转一圈再来。你们帮我把法国馆看好。我叮嘱完他们,便到街上去买东西吃。 街上的东西形形色色。有的场馆中,围满...
    roxann阅读 90评论 0 0