-
threading 的多线程并发
threading 的多线程并发 对 比多进程并发:
*消耗资源较少
*线程应该更注意共享资源的操作
*在Pythonh中应该注意GIT问题,网络延迟较高,线程并发也是一种可行的操作
实现步骤:
1.创建套接字
2.接受客户端请求,创建新的线程
3.主程序继续接受其他客户端连接
4.分支线程启动对应的函数处理客户端请求
5.当客户端断开,则分支线程结束
# socket_server.py
from socketserver import *
# 创建服务器类
class Server(ForkingMixIn,TCPServer):
pass
class Handler(StreamRequestHandler):
def handle(self):
# self.request ==> accept 返回的套接字
print('Connect from', self.request.getpeername())
while True:
data = self.request.recv(1024)
if not data:
break
print(data.decode())
self.request.send(b'Recive')
if __name__=="__main__":
server_addr = ('0.0.0.0', 9999)
# 创建服务器对象
server = Server(server_addr, Handler)
# 启动服务器
server.serve_forever()
cookie
import traceback
功能:更详细的打印异常信息
traceback.print_exc()
功能:更详细的打印异常信息
集成模块的使用
python2 SocketServer
python3 socketserver
功能:通过模块的不同 类的组合完成多进程,多线程的tcp/udp的并发
StreamRequestHandler 处理tcp套接字请求
DatagramRequestHandler 处理udp套接字请求
TCPServer 创建tcp server
UDPServer 创建ucp server
ForkingMixIn 创建多进程
ForkingTCPServer -->ForkingMixIn + TCPServer
ForkingUDPServer -->ForkingMixIn + UDPServer
ThreadingMixIn 创建多线程
ThreadingTCPServer -->ThreadingMixIn + TCPServer
ThreadingUDPServer -->ThreadingMixIn + UDPServer
HTTPServer v2.0
1.接收客户端请求
2.解析客户端请求
3.组织数据形成HTTP reponse
4.将数据发给客户端
升级
1.采用多线程并发接收多个客户端请求
2.基本的请求解析,根据请求返回相应的内容
3.除了可以请求静态网页,也可以请求简单的数据
4.将功能封装在一个类中
技术点:
1.socket tcp 套接字
2.http协议的请求相应格式
3.线程并发的创建方法
4.类的基本使用
#!usr/bin/env python3
# coding=utf-8
'''
1.多线程并发
2.可以请求简单数据
3.能进行简单请求分析
4.结构使用类进行封装
'''
from socket import *
from threading import Thread
import sys
import traceback
# HTTPserver类,封装具体的服务器功能
class HttpServer(object):
def __init__(self, server_addr, static_dir):
# 增添服务器对象属性
self.server_address = server_addr
self.static_dir = static_dir # 我的静态页面存储目录
self.ip = server_addr[0] # 地址
self.port = server_addr[1] # 端口
# 创建套接字
self.create_socket()
def create_socket(self):
self.sockfd = socket()
self.sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 释放端口
self.sockfd.bind(self.server_address) # 连接
def serve_forever(self):
self.sockfd.listen(5)
print('Listen the port %d' % self.port)
while True:
try:
connfd, addr = self.sockfd.accept()
except KeyboardInterrupt:
self.sockfd.close()
sys.exit('服务器退出')
except Exception:
traceback.print_exc()
continue
# 创建新的线程处理请求
clientThread = Thread(target=self.handleRequest,
args=(connfd,))
clientThread.setDaemon(True)
clientThread.start()
# 客户端请求函数
def handleRequest(self, connfd):
# 接收客户端请求
request = connfd.recv(4096)
# 解析请求内容
requestHeaders = request.splitlines()
print(connfd.getpeername(), ":", requestHeaders[0])
# 获取具体请求内容
getRequest = str(requestHeaders[0]).split(' ')[1]
if getRequest == '/' or getRequest[-5:] == './html':
self.get_html(connfd, getRequest)
else:
self.get_data(connfd, getRequest)
connfd.close()
def get_html(self, connfd, getRequest):
if getRequest == '/':
filename = self.static_dir + '/index.html'
else:
filename = self.static_dir + getRequest
try:
f = open(filename)
except Exception:
# 没有找到网页
responseHeaders = 'HTTP/1.1 404 NOT FOUND\r\n'
responseHeaders += '\r\n'
responseBody = 'sorry,not found the page'
else:
responseHeaders = 'HTTP/1.1 200 OK\r\n'
responseHeaders += '\r\n'
responseBody = f.read()
finally:
response = responseHeaders + responseBody
connfd.send(response.encode())
def get_data(self, connfd, getRequest):
urls = ['/time', '/tedu', '/python']
if getRequest in urls:
responseHeaders = 'HTTP/1.1 200 OK\r\n'
responseHeaders += '\r\n'
if getRequest == '/time':
import time
responseBody = time.ctime()
elif getRequest == '/tedu':
responseBody = 'welcome to tarena'
elif getRequest == '/python':
responseBody = '人生苦短我用Python'
else:
responseHeaders = 'HTTP/1.1 404 NOT FOUND\r\n'
responseHeaders += '\r\n'
responseBody = 'sorry,not found the page'
response = responseHeaders + responseBody
connfd.send(response.encode())
if __name__ == "__main__":
# 服务器IP
server_addr = ('0.0.0.0', 8888)
# 我的静态页面存储目录
static_dir = './static'
# 生成对象
httpd = HttpServer(server_addr, static_dir)
# 启动服务器
httpd.serve_forever()