前言:此为python学习笔记,如错误或争议敬请发送到邮箱 zytwell321@163.com ,万分感谢!
1.单线程服务
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# author:Torry Zhang
# contact: zytwell321@163.com
# datetime:2020/8/13 18:15
# software: PyCharm
"""
1.根据用户请求,返回所需的页面
2.直接请求服务器端口,返回默认页面
"""
import socket
import re
def service_client(new_socket):
""" 为客户端提供返回数据 """
# 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
# ...
request_data = new_socket.recv(1024).decode("utf-8")
print(request_data)
# 将请求结果分割成列表
request_lines = request_data.splitlines()
# print(">" * 20)
# print(request_lines)
# GET /html/index.html HTTP/1.1
# GET / HTTP/1.1
# 请求类型:GET POST DELETE ...
file_name = ""
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
if ret:
file_name = ret.group(1) # 提取请求路径
print("*" * 30, file_name)
if file_name == "/":
file_name = "/index.html"
# 2.返回http格式信息给客户端浏览器
try:
f = open("./html" + file_name, "rb") # 打开url访问路径文件
except:
response = "HTTP/1.1 404\r\n"
response += "\r\n"
response += "<h1>404</h1>\r\nFILE NOT FOUND"
new_socket.send(response.encode("utf-8"))
else:
html_content = f.read()
f.close()
# 2.1 组装返回给浏览器的数据-- header
print(" " * 50)
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 2.2 组装返回给浏览器的数据-- body
# response += "<h1>hello world</h1>\r\n" # 调试:返回固定结果
# f = open("./html/test.html", "rb") # 调试:返回固定页面
# 返回给浏览器报文头 respone header
new_socket.send(response.encode("utf-8"))
# 返回给浏览器报文体 reponse body
new_socket.send(html_content)
# 3.关闭套接字
new_socket.close()
def main():
""" tcp-socket 流程控制 """
# 1.创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2.绑定
tcp_socket_server.bind(("",8080))
# 3.创建套接字监听
tcp_socket_server.listen(128)
# 4.服务完毕,关闭套接字
while True:
# 4.等待新客户端连接
new_socket, client_addr = tcp_socket_server.accept()
# 5.为客户端提供服务
service_client(new_socket)
tcp_socket_server.close()
if __name__ == "__main__":
main()
浏览器显示内容:
服务端接收到请求:
GET / HTTP/1.1
Host: 127.0.0.1:8080
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/83.0.4103.106 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;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
****************************** /
遗留问题:
浏览器访问连接一段时间后,断开服务端。服务端响应提示如下:
Traceback (most recent call last):
File "F:/develop/python/stu/PycharmProjects/forPythonStu/web/socket_server.py", line 88, in <module>
main()
File "F:/develop/python/stu/PycharmProjects/forPythonStu/web/socket_server.py", line 82, in main
service_client(new_socket)
File "F:/develop/python/stu/PycharmProjects/forPythonStu/web/socket_server.py", line 31, in service_client
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
IndexError: list index out of range
2.多进程服务
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# author:Torry Zhang
# contact: zytwell321@163.com
# datetime:2020/8/13 18:15
# software: PyCharm
"""
1.根据用户请求,返回所需的页面
2.直接请求服务器端口,返回默认页面
"""
import socket
import re
import multiprocessing
def service_client(new_socket):
""" 为客户端提供返回数据 """
# 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
# ...
request_data = new_socket.recv(1024).decode("utf-8")
print(request_data)
# 将请求结果分割成列表
request_lines = request_data.splitlines()
# print(">" * 20)
# print(request_lines)
# GET /html/index.html HTTP/1.1
# GET / HTTP/1.1
# 请求类型:GET POST DELETE ...
file_name = ""
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
if ret:
file_name = ret.group(1) # 提取请求路径
print("*" * 30, file_name)
if file_name == "/":
file_name = "/index.html"
# 2.返回http格式信息给客户端浏览器
try:
f = open("./html" + file_name, "rb") # 打开url访问路径文件
except:
response = "HTTP/1.1 404\r\n"
response += "\r\n"
response += "<h1>404</h1>\r\nFILE NOT FOUND"
new_socket.send(response.encode("utf-8"))
else:
html_content = f.read()
f.close()
# 2.1 组装返回给浏览器的数据-- header
print(" " * 50)
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 2.2 组装返回给浏览器的数据-- body
# response += "<h1>hello world</h1>\r\n" # 调试:返回固定结果
# f = open("./html/test.html", "rb") # 调试:返回固定页面
# 返回给浏览器报文头 respone header
new_socket.send(response.encode("utf-8"))
# 返回给浏览器报文体 reponse body
new_socket.send(html_content)
# 3.关闭套接字
new_socket.close()
def main():
""" tcp-socket 流程控制 """
# 1.创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2.绑定
tcp_socket_server.bind(("",8080))
# 3.创建套接字监听
tcp_socket_server.listen(128)
# 4.服务完毕,关闭套接字
while True:
# 4.等待新客户端连接
new_socket, client_addr = tcp_socket_server.accept()
# 5.为客户端提供服务
# service_client(new_socket)
p = multiprocessing.Process(target=service_client, args=(new_socket,))
p.start()
new_socket.close()
tcp_socket_server.close()
if __name__ == "__main__":
main()
3.多线程服务
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# author:Torry Zhang
# contact: zytwell321@163.com
# datetime:2020/8/13 18:15
# software: PyCharm
"""
1.根据用户请求,返回所需的页面
2.直接请求服务器端口,返回默认页面
"""
import socket
import re
import threading
def service_client(new_socket):
""" 为客户端提供返回数据 """
# 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
# ...
request_data = new_socket.recv(1024).decode("utf-8")
print(request_data)
# 将请求结果分割成列表
request_lines = request_data.splitlines()
# print(">" * 20)
# print(request_lines)
# GET /html/index.html HTTP/1.1
# GET / HTTP/1.1
# 请求类型:GET POST DELETE ...
file_name = ""
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
if ret:
file_name = ret.group(1) # 提取请求路径
print("*" * 30, file_name)
if file_name == "/":
file_name = "/index.html"
# 2.返回http格式信息给客户端浏览器
try:
f = open("./html" + file_name, "rb") # 打开url访问路径文件
except:
response = "HTTP/1.1 404\r\n"
response += "\r\n"
response += "<h1>404</h1>\r\nFILE NOT FOUND"
new_socket.send(response.encode("utf-8"))
else:
html_content = f.read()
f.close()
# 2.1 组装返回给浏览器的数据-- header
print(" " * 50)
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 2.2 组装返回给浏览器的数据-- body
# response += "<h1>hello world</h1>\r\n" # 调试:返回固定结果
# f = open("./html/test.html", "rb") # 调试:返回固定页面
# 返回给浏览器报文头 respone header
new_socket.send(response.encode("utf-8"))
# 返回给浏览器报文体 reponse body
new_socket.send(html_content)
# 3.关闭套接字
new_socket.close()
def main():
""" tcp-socket 流程控制 """
# 1.创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2.绑定
tcp_socket_server.bind(("",8080))
# 3.创建套接字监听
tcp_socket_server.listen(128)
# 4.服务完毕,关闭套接字
while True:
# 4.等待新客户端连接
new_socket, client_addr = tcp_socket_server.accept()
# 5.为客户端提供服务
# service_client(new_socket)
t = threading.Thread(target=service_client, args=(new_socket,))
t.start()
tcp_socket_server.close()
if __name__ == "__main__":
main()
4.协程实现http服务
"""
使用协程完成http服务器
"""
import socket
import re
import gevent
from gevent import monkey
monkey.patch_all()
def service_client(new_socket):
""" 为客户端提供返回数据 """
# 1.接收客户端浏览器发送过来的数据,如:GET / HTTP/1.1
# ...
request_data = new_socket.recv(1024).decode("utf-8")
print(request_data)
# 将请求结果分割成列表
request_lines = request_data.splitlines()
# print(">" * 20)
# print(request_lines)
# GET /html/index.html HTTP/1.1
# GET / HTTP/1.1
# 请求类型:GET POST DELETE ...
file_name = ""
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
if ret:
file_name = ret.group(1) # 提取请求路径
print("*" * 30, file_name)
if file_name == "/":
file_name = "/index.html"
# 2.返回http格式信息给客户端浏览器
try:
f = open("./html" + file_name, "rb") # 打开url访问路径文件
except:
response = "HTTP/1.1 404\r\n"
response += "\r\n"
response += "<h1>404</h1>\r\nFILE NOT FOUND"
new_socket.send(response.encode("utf-8"))
else:
html_content = f.read()
f.close()
# 2.1 组装返回给浏览器的数据-- header
print(" " * 50)
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 2.2 组装返回给浏览器的数据-- body
# response += "<h1>hello world</h1>\r\n" # 调试:返回固定结果
# f = open("./html/test.html", "rb") # 调试:返回固定页面
# 返回给浏览器报文头 respone header
new_socket.send(response.encode("utf-8"))
# 返回给浏览器报文体 reponse body
new_socket.send(html_content)
# 3.关闭套接字
new_socket.close()
def main():
""" tcp-socket 流程控制 """
# 1.创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置当前服务器先close 即服务器端4次挥手后资源能够立即释放。保证下次程序启用时,可以立即启用端口
tcp_socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2.绑定
tcp_socket_server.bind(("",8080))
# 3.创建套接字监听
tcp_socket_server.listen(128)
# 4.服务完毕,关闭套接字
while True:
# 4.等待新客户端连接
new_socket, client_addr = tcp_socket_server.accept()
# 5.为客户端提供服务
gevent.spawn(service_client, new_socket)
#tcp_socket_server.close()
if __name__ == "__main__":
main()