目录
day09
cookie:
- os.listdir(path)
功能:获取文件列表
- os.path.isfile() 判断一个文件是否为普通文件
- os.path.isdir() 判断一个文件是否为目录
多线程并发
threading 模块完成多线程并发
- 对比多进程并发
- 优势:资源消耗少
- 缺点:需要注意对共享资源的操作
- 实现步骤
- 创建套接字,绑定,监听
- 接收客户端连接请求,创建新的线程
- 主线程继续等待其他客户端连接,分支线程执行客户端具体请求
- 处理完客户端请求后分支线程自然退出,关闭客户端套接字
客户端可查阅python 网络编程 day01 - 示例:
from socket import *
import os,sys
from threading import *
HOST = "0.0.0.0"
PORT = 8888
ADDR = (HOST,PORT)
#客户端处理函数
def handler(connfd):
print("Connect from",connfd.getpeername())
while True:
data = connfd.recv(1024).decode()
if not data:
break
print(data)
connfd.send(b'Receive your msg')
connfd.close()
s = socket()
s.bind(ADDR)
s.listen(5)
while True:
try:
connfd,addr = s.accept()
except KeyboardInterrupt:
s.close()
sys.exit("服务器退出")
except Exception as e:
print(e)
continue
t = Thread(target=handler,args= (connfd,))
t.setDaemon(True)
t.start()
socket并发集成模块
- python2 SocketServer
- python3 sockerserver
- 功能:通过模块提供的接口组合可以完成多进程/多线程 tcp/udp的并发程序
'StreamRequestHandler', 处理tcp请求
'DatagramRequestHandler', 处理udp请求'ForkingMixIn', 建立多进程
'ThreadingMixIn', 建立多线程'TCPServer', 建立tcp server
'UDPServer', 建立udp server'ForkingTCPServer', ForkingMixIn + TCPServer 建立多进程tcp server
'ForkingUDPServer', ForkingMixIn + UDPServer 建立多进程udp server
'ThreadingTCPServer', ThreadingMixIn + TCPServer 建立多线程tcp server
'ThreadingUDPServer', ThreadingMixIn + UDPServer 建立多线程udp server
多进程多线程tcp:
#多进程 tcp server
from socketserver import *
#创建server类
# class Server(ForkingMixIn,TCPServer):
# class Server(ForkingTCPServer):
# pass
#多线程tcp并发
class Server(ThreadingTCPServer):
pass
#具体的请求处理类
class Handler(StreamRequestHandler):
def handle(self):
# self.request ==> accept返回的套接字
print("Connect from",\
self.request.getpeername())
while True:
data = self.request.recv(1024).decode()
if not data:
break
print(data)
self.request.send(b'Receive')
#创建server对象
server = Server(("0.0.0.0",8888),Handler)
#启动服务器
server.serve_forever()
多进程udp:
from socketserver import *
class Server(ForkingMixIn,UDPServer):
pass
class Handler(DatagramRequestHandler):
def handle(self):
while True:
data = self.rfile.readline().decode()
if not data:
break
print(data)
#发送消息
self.wfile.write(b"Receive\n")
server = Server(('0.0.0.0',8888),Handler)
server.serve_forever()
基于多线程并发的HTTPserver
- 接受浏览器请求
- 对请求进行一定的解析
- 根据解析内容返回对应的内容
- 如果没有请求内容则返回404
- 组织Response格式进行回发
升级
- 使用多线程并发
- 增加了具体的请求解析和404情况
- 使用类进行代码封装
- 增加一定的数据获取功能
技术点:
- threading并发
- tcp socket
- HTTP协议响应和请求的格式
解析:
from socket import *
from threading import Thread
import time
#存放静态页面
STATIC_DIR = "./static"
ADDR = ('0.0.0.0',8000)
#HTTPServer类,封装具体功能
class HTTPServer(object):
def __init__(self,address):
#创建套接字
self.sockfd = socket()
self.sockfd.setsockopt\
(SOL_SOCKET,SO_REUSEADDR,1)
self.sockfd.bind(address)
self.sockfd.listen(5)
#为对象增加属性变量
self.name = "HTTPServer"
self.port = address[1]
self.address = address
#启动服务器
def serve_forever(self):
print("Listen the port %d"%self.port)
while True:
connfd,addr = self.sockfd.accept()
#创建线程处理具体请求
clientThread = Thread\
(target = self.handleRequest,args = (connfd,))
clientThread.setDaemon(True)
clientThread.start()
def handleRequest(self,connfd):
#接收客户端请求
request = connfd.recv(4096)
#按行切割 字符串
requestHeadlers = request.splitlines()
#获取请求行
print(connfd.getpeername(),":",\
requestHeadlers[0])
#获取请求内容
getRequest = str(requestHeadlers[0]).split(' ')[1]
if getRequest == '/' or getRequest[-5:] == '.html':
data = self.get_html(getRequest)
else:
data = self.get_data(getRequest)
connfd.send(data.encode())
connfd.close()
def get_html(self,page):
if page == "/":
filename = STATIC_DIR + "/index.html"
else:
filename = STATIC_DIR + page
try:
f = open(filename)
except Exception:
#没有找到页面
responseHeadlers = "HTTP/1.1 404 Not Found\r\n"
responseHeadlers += "Content-Type: text/html\r\n"
responseHeadlers += '\r\n'
responseBody = "<h1>Sorry,not found the page</h1>"
else:
responseHeadlers = "HTTP/1.1 200 OK\r\n"
responseHeadlers += "Content-Type: text/html\r\n"
responseHeadlers += '\r\n'
responseBody = f.read()
finally:
return responseHeadlers + responseBody
def get_data(self,data):
responseHeadlers = "HTTP/1.1 200 OK\r\n"
responseHeadlers += "\r\n"
if data == "/time":
responseBody = time.ctime()
elif data == "/tedu":
responseBody = "Welcome to tedu"
else:
responseBody = "The data not found"
return responseHeadlers + responseBody
if __name__ == "__main__":
#生成服务器对象
httpd = HTTPServer(ADDR)
#启动服务器
httpd.serve_forever()
3个小插曲:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主页</title>
</head>
<body>
<h1>这是主页</h1>
<p>达内科技欢迎你</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="main">
<div class="header" >
<h1>Login!</h1>
</div>
<p></p>
<form action="" method="post">
<ul class="right-form">
<h2>Login:</h2>
<li><input type="text" name="username" placeholder="Username" required/></li>
<li><input type="password" name="password" placeholder="Password" required/></li>
<input type="hidden" name="source_url" value="aaaa">
<input type="submit" value="Login" >
<div class="clear"> </div>
</ul>
<div class="clear"> </div>
</form>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>操作成功</title>
<link href="http://www.maiziedu.com/static/css/base.css" rel="stylesheet">
<link href="http://www.maiziedu.com/static/css/microoh-v5.css" rel="stylesheet">
</head>
<body>
<div class="microoh-main" style="height: 100px">
<div style="position: absolute; top: 20px; left: 20px;">
<i class="v5-icon v5-icon-right"></i>
</div>
</div>
</body>
</html>
作业 :
- 总结进程线程和网络中的概念问答题
- 聊天室,tftp文件服,httpserver第二版
- 复习规划