硬件服务器: 主机 集群
厂商: IBM HP 联想 浪潮
软件服务器: 编写的服务端应用程序,在硬件服务器上运行,一般依托于操作系统,给用户提供一套完整的服务
httpserver ---> 处理http请求
webserver ---> 网站的后端应用服务器程序
邮箱服务器 ---> 邮件处理
ftp文件服务器 --> 文件的上传下载
功能:网络连接 逻辑处理 数据交互 数据传输 协议的实现
结构: c/s 客户端服务器模型
b/s 浏览器服务器模型
服务器目标: 处理速度更快,并发量更高,安全性更强
硬件:更高的配置,更好的集成分配技术,更好的网络优化和网络安全技术
软件:占用资源更少,运行更稳定,算法更优良,安全性更好,并发性更高,更容易扩展
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/532239be5e6f37984fa50e1bbfc15b13.png)
1.循环模型: 循环接收客户端请求,处理请求。同一时刻只能处理一个请求,处理完毕后再处理下一个。
优点: 实现简单、占用资源少、
缺点: 无法同时处理多个客户端任务
使用情况: 处理的任务的可以短时间完成,不需要建立并发,更适合udp使用
2.并发模型: 能够同时处理多个客户端请求
类型:
IO并发: IO多路复用
优点: 资源消耗少,IO处理速度快
缺点: 不能适用CPU密集型程序
多进程/多线程并发: 为每个客户端创建单独的进程线程,执行请求
优点:每个客户端可以长期占有服务器运行程序,能够使用多核资源,能够处理CPU或IO运算
缺点: 消耗系统资源高
流程:
1.创建套接字,绑定,监听
2.等待接收客户端请求
3.创建新的进程处理客户端请求
4.原来进程继续等待接收新的客户端连接
5.如果客户端退出则关闭子进程
Cookie:
在父进程中忽略子进程状态改变,子进程退出自动由系统处理,避免僵尸进程的产生
signal.signal(signal.SIGCHID,signal.SIG_IGN)
#使用多进程并发构建基础服务器
#父进程用来构建连接,多个子进程用来通信
from socket import *
import os,sys
import signal
def client_handler(c):
#子进程用来通信
print('处理子进程的请求:',c.getpeername())
try:
while True:
data = c.recv(1024)
if not data:
break
print(data.decode())
c.send('收到客户端请求'.encode())
except (KeyboardInterrupt,SystemError):
sys.exit('客户端退出')
except Exception as e:
print(e)
print('子进程退出:',c.getpeername())
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('进程{}等待客户端连接'.format(os.getpid()))
#在父进程中忽略子进程状态改变,子进程退出自动由系统处理从而避免僵尸进程
signal.signal(signal.SIGCHLD,signal.SIG_IGN)
while True:
try:
c,addr = s.accept()
except KeyboardInterrupt:
sys.exit('服务器退出') # os._exit(0)但不能提示消息
except Exception as e:
print('Error:',e)
continue
#为客户端创建新的进程,处理请求
pid = os.fork()
#子进程处理具体请求
if pid == 0:
s.close() # 子进程copy父进程的资源,其中多余的s需要关闭
client_handler(c)
# 父进程或者创建进程失败都继续等待下个客户端连接
else:
c.close() # 父进程中的c同样需要关闭
continue