python 线程并发 day09

目录

多线程并发

socket并发集成模块

基于多进程并发的HTTPserver


day09

cookie:

  • os.listdir(path)
    功能:获取文件列表
     
  • os.path.isfile() 判断一个文件是否为普通文件
  • os.path.isdir()  判断一个文件是否为目录

多线程并发

threading 模块完成多线程并发

  • 对比多进程并发
  1. 优势:资源消耗少
  2. 缺点:需要注意对共享资源的操作
  • 实现步骤
  1. 创建套接字,绑定,监听
  2. 接收客户端连接请求,创建新的线程
  3. 主线程继续等待其他客户端连接,分支线程执行客户端具体请求
  4. 处理完客户端请求后分支线程自然退出,关闭客户端套接字
    客户端可查阅python 网络编程 day01
  5. 示例:
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

  1. 接受浏览器请求
  2. 对请求进行一定的解析
  3. 根据解析内容返回对应的内容
  4. 如果没有请求内容则返回404
  5. 组织Response格式进行回发

  升级

  1. 使用多线程并发
  2. 增加了具体的请求解析和404情况
  3. 使用类进行代码封装
  4. 增加一定的数据获取功能

  技术点:

  • 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>

作业 :

  1.  总结进程线程和网络中的概念问答题
  2. 聊天室,tftp文件服,httpserver第二版
  3. 复习规划

猜你喜欢

转载自blog.csdn.net/qq_42584444/article/details/81735395