python服务器开发代码_利⽤Python搭建简单的多线程Web服
务器-代码⽰例(基于T。。。
多任务版web服务器程序的实现:
web服务器基于TCP服务端开发,其基本构成都是相同的,但有最⼤⼀点的差异是:
客户端请求及服务端响应的内容,必须符合html协议,否则将⽆法获取数据。
客户端请求报⽂格式⽰例:
# 请求⾏(还有POST请求⽅式)
GET / HTTP/1.1\r\n
# 请求体
Host: www.itcast\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/69.0.3497.100 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8\r\n
Accept-Encoding: gzip, deflate\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
webserver接口开发
Cookie: pgv_pvi=1246921728; \r\n
# 空⾏(不能省略)
\r\n
服务端响应报⽂格式⽰例:
# 响应⾏
HTTP/1.1 200 OK\r\n
# 响应体
Server: Tengine\r\n
Content-Type: text/html; charset=UTF-8\r\n
Transfer-Encoding: chunked\r\n
Connection: keep-alive\r\n
Date: Fri, 23 Nov 2018 02:01:05 GMT\r\n
# 空⾏(不能省略)
\r\n
# 响应体(正⽂)
特别说明:
每项数据之后都要使⽤:\r\n(见格式⽰例)
以上内容为web传输与普通TCP传输代码的差异。
本⽂以多线程web客户端作为代码⽰例。
当客户端和服务端建⽴连接成功,创建⼦线程,使⽤⼦线程专门处理客户端的请求,防⽌主线程阻塞。
把创建的⼦线程设置成为守护主线程,防⽌主线程⽆法退出。
代码⽰例
注:代码中使⽤的html源⽂件是提前放在代码⽂件同级⽬录中static⽬录下的,你可以在⽹上到⽤于练习的html⽂件。使⽤的html⽂件
import threading
import socket
def handle_recv(new_socket, ip_port):
print("客户端已连接:", ip_port)
# 获取浏览器发送的http请求报⽂数据并解码
recieve_content = v(4096).decode("utf-8")
print(recieve_content)
# 获取⽤户请求资源的路径(根据浏览器发送的请求⾏提取)
path = recieve_content.split(" ",maxsplit=3)[1]
# 指定如果访问根⽬录时,返回index.html内容
if path == "/":
path = "/index.html"
# 响应⾏
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_headers = "Content-Type: text/html;charset=utf-8\r\n"
# 加⼊判断,如请求的路径存在,则正常返回,当客服端请求的路径不存在时,返回错误页⾯
try:
with open("./static%s" % path, "rb") as f:
response_body = f.read()
except FileNotFoundError:
response_line = "HTTP/1.1 404 NOT FOUND\r\n"
path = "/error.html"
with open("./static%s" % path, "rb") as f:
response_body = f.read()
# 服务端发送符合html要求的数据给客服端
new_socket.send((response_line + response_headers + "\r\n").encode("utf-8") + response_body)
new_socket.close()
if __name__ == '__main__':
# 创建服务端tcp socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 程序退出端⼝号⽴即释放
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定端⼝号
server_socket.bind(("", 8090))
# 设置监听
server_socket.listen(128)
# 循环等待接受客户端的连接请求
while True:
# 主线程负责创建新的套接字接⼝
new_socket, ip_port = server_socket.accept()
# 当客户端和服务端建⽴连接成功,创建⼦线程,使⽤⼦线程专门处理客户端的请求,防⽌主线程阻塞。
sub_thread = threading.Thread(target=handle_recv,args=(new_socket, ip_port))
# 把创建的⼦线程设置成为守护主线程,防⽌主线程⽆法退出。
sub_thread.setDaemon(True)
# 启动线程执⾏对应的任务
sub_thread.start()
服务端窗⼝返回接收到的浏览器请求数据如下,提取的请求⽂件路径即是通过第⼀⾏的请求⾏提取:
客户端已连接: ('127.0.0.1', 53729)
客户端已连接: ('127.0.0.1', 53730)
GET /index2.html HTTP/1.1 #请求⾏
Host: 127.0.0.1:8090
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/73.0.3683.103 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
GET /web.jpg HTTP/1.1
Host: 127.0.0.1:8090
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
Accept: image/webp,image/apng,image/,/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
客服端浏览器返回的页⾯如下:
image.png
当输⼊不存在的页⾯时:
将返回设定好的404错误页⾯,可以看到,页⾯的响应体和状态信息和我们代码中设置的⼀致。
image.png
将代码改写为⾯向对象编程结构
构造⾯向对象的代码块,将可以在复⽤时⾮常⽅便的创建新服务器对象。
import threading
import socket
class HTTPWebServer(object):
def __init__(self,port):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("", port))
server_socket.listen(128)
self.server_socket = server_socket
@staticmethod
def handle_recv(new_socket, ip_port):
print("客户端已连接:", ip_port)
recieve_content = v(1024).decode("utf-8")
print(recieve_content)
path = recieve_content.split(" ",maxsplit=2)[1]
if path == "/":
path = "/index.html"
response_line = "HTTP/1.1 200 OK\r\n"
response_headers = "Content-Type: text/html;charset=utf-8\r\n"
try:
with open("./static%s" % path, "rb") as f:
response_body = f.read()
except FileNotFoundError:
response_line = "HTTP/1.1 404 NOT FOUND\r\n"
path = "/error.html"
with open("./static%s" % path, "rb") as f:
response_body = f.read()
new_socket.send((response_line + response_headers + "\r\n").encode("utf-8") + response_body) new_socket.close()
def start(self):
while True:
new_socket, ip_port = self.server_socket.accept()
sub_thread = threading.Thread(target=self.handle_recv,args=(new_socket, ip_port))
sub_thread.setDaemon(True)
sub_thread.start()
if __name__ == '__main__':
port = 8080
server = HTTPWebServer(port)
server.start()
⼩结
这样就完成了⼀个简单的web服务器,可⽤于浏览器访问。
当客户端和服务端建⽴连接成功,创建⼦线程,使⽤⼦线程专门处理客户端的请求,防⽌主线程阻塞。
使⽤.setDaemon(True)设置主线程守护,防⽌主线程⽆法退出。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。