软件服务器:编写的服务端应用程序, 在硬件服务器上运行, 一般依托于操作系统,给用户提供一套完整的服务
httpserver 处理Http请求
webserver 网站的后端应用服务器程序
邮箱服务器 邮件处理
ftp文件服务器 文件的上传下载
功能:网络连接 逻辑处理 数据交互 数据传输 协议的实现
结构:
c/s 客户端服务器模型
b/s 浏览器服务器模型
服务器目标:处理速度更快,并发量更高,安全性更强
硬件:更高的配置,更好的集成分布技术,更好的网络优化和网络安全技术
软件:占用资源更少,运行更稳定,算法更优良,安全性更好,并发性更高,更容易扩展
基础服务模型
循环模型:循环接收客户端请求,处理请求。同一时刻只能处理一个请求,处理完毕后再处理下一个
优点:实现简单,占用资源少
缺点:无法同时处理多个客户端任务
适用情况:处理的任务可以短时间完成,不需要建立并发,更适合udp使用- 并发模型:能够同时处理多个客户端请求
- IO并发:IO多路复用
优点:资源消耗少,IO处理速度快
缺点:不能适用cpu密集型程序 - 多进程/多线程并发:为每个客户端创建单独的进程线程,执行请求
优点:每个客户端可以长期占有服务器运行程序,能够使用多核资源 ,可以处理IO或者cpu运算
缺点:消耗系统资源高
- IO并发:IO多路复用
多进程并发模型
使用fork实现进程并发
- 创建套接字,绑定,监听
- 等待接收客户请求
- 创建新的进程处理客户端请求
- 原有进程继续等待接收新的客户端连接
- 如果客户端退出则关闭子进程
# fork_server.py
from socket import *
import os
import sys
import signal
# 客户端处理函数
def client_handler():
print('处理子进程的请求:', c.getpeername())
try:
while True:
data = c.recv(1024)
if not data:
break
print(data)
c.send('收到客户端请求'.encode())
except (KeyboardInterrupt, SystemError):
sys.exit('客户端退出')
except Exception as e:
print(e)
c.close()
sys.exit(0)
# 创建套接字
HOST = "" # '0.0.0.0'
PORT = 8888
ADDR = (HOST, PORT)
s = socket()
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(ADDR)
s.listen(5)
print('进程%d等待客户端连接' % os.getpid())
# 在父进程中忽略子进程状态改变,子进程退出自动由系统处理
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
while True:
try:
c, addr = s.accept()
except KeyboardInterrupt:
sys.exit('服务器退出')
except Excepton as e:
print('Error:', e)
continue
# 为客户端创建新的进程,处理请求
pid = os.fork()
# 子进程处理具体请求
if pid == 0:
s.close()
client_handler()
# 父进程或者创建失败都继续等待下个客户端连接
else:
c.close()
continue
cookie:
在父进程中忽略子进程状态改变,子进程退出自动由系统处理
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
ftp文件服务器
项目功能
- 服务端和客户端两部分,要求启动一个服务端,可以同时处理多个客户端请求
- 功能:
- 可以查看服务端文件库中所有的普通文件
- 从客户端可以下载文件库的文件到本地
- 可以将本地文件上传的服务端文件库
- 退出
- 客户端使用print在终端打印简单的命令提示,通过命令提示发起请求
- 技术分析(fork, tcp, 并发)
- 每个功能要单独封装,整体功能写在一个类中
- 如何搭建整体架构,完成网络通讯
cookie
os.listdir(path)
os.path.isfile()
os.path.isdir()