程序中所用到的文件html是一个网页页面文件,不再上传。
使用多进程完成http服务器
import socket
import re
import multiprocessing
def sever_client(new_socket):
"""为客户端返回数据"""
# 接受客户端发送来的请求
# while True:
request = new_socket.recv(1024).decode("utf-8")
print(request)
# 切割为列表
request_lines = request.splitlines()
print(">" * 10)
print(request_lines)
if request_lines:
# GET /index.html HTTP/1.1
# get post put del
ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0]).group(1)
if ret == "/":
ret = "/index.html"
# 返回http格式的数据给浏览器
try:
with open("./html" + ret, "rb") as f:
html_content = f.read()
response = "HTTP/1.1 200 OK\r\n\r\n"
new_socket.send(response.encode("utf-8"))
new_socket.send(html_content)
print("***"*3)
except:
response = "HTTP/1.1 404 NOT FOUND\r\n"
response += "Content-type:text/html;charset=utf-8\r\n\r\n"
response += "文件不存在,NOT FOUND"
new_socket.send(response.encode("utf-8"))
# else:
# break
# 关闭套接字
new_socket.close()
def main():
"""用来完成整体的控制"""
# 创建套接字
tcp_sever_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_sever_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定套接字
tcp_sever_socket.bind(("", 7890))
# 变为监听套接字
tcp_sever_socket.listen(128)
while True:
# 等待客户端连接
print("等待连接")
new_socket, client_addr = tcp_sever_socket.accept()
# 为这个客户端服务
p = multiprocessing.Process(target=sever_client, args=(new_socket,))
p.start()
# 关闭套接字,由于进程会复制一份资源所以必须立马关闭一个
new_socket.close()
# 关闭监听套接字
tcp_sever_socket.close()
if __name__ == '__main__':
main()
使用多线程实现http服务器
import socket
import threading
import re
def service_client(new_socket):
request = new_socket.recv(1024).decode("utf-8")
print(">>>>"*10)
ret = re.match(r"[^/]+(/[^ ]*)", request)
if ret:
ret = ret.group(1)
if ret == "/":
ret = "/index.html"
try:
with open("./html" + ret, "rb") as f:
html_content = f.read()
response = "HTTP/1.1 200 OK\r\n\r\n"
new_socket.send(response.encode("utf-8"))
new_socket.send(html_content)
except:
response = "HTTP/1.1 404 NOT FOUND\r\n\r\n"
response += "----file not found---"
new_socket.send(response.encode("utf-8"))
new_socket.close()
def main():
"""多线程实现http服务器"""
# 创建套接字
tcp_sever_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_sever_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定
tcp_sever_socket.bind(("",7890))
# 变为监听套接字
tcp_sever_socket.listen(128)
while True:
# 等待客户端连接
print("等待连接")
new_socket,client_addr = tcp_sever_socket.accept()
# 为这个客户端服务
p = threading.Thread(target=service_client,args=(new_socket,))
p.start()
tcp_sever_socket.close()
if __name__ == '__main__':
main()
使用协程gevent完成http服务器
import socket
import re
import gevent
from gevent import monkey
monkey.patch_all()
def service_client(new_socket):
"""为这个客户端返回数据"""
# 接受数据
request = new_socket.recv(1024).decode("utf-8")
ret = re.match(r"[^/]+(/[^ ]*)",request)
if ret:
ret = ret.group(1)
if ret == "/":
ret = "/index.html"
try:
with open("./html" + ret, "rb") as f:
html_content = f.read()
response = "HTTP/1.1 200 OK\r\n\r\n"
new_socket.send(response.encode("utf-8"))
new_socket.send(html_content)
except:
response = "HTTP/1.1 404 NOT FOUND\r\n\r\n"
response += "-----file not found----"
new_socket.send(response.encode("utf-8"))
new_socket.close()
def main():
"""使用协程实现http服务器"""
# 创建套接字
tcp_sever_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_sever_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定
tcp_sever_socket.bind(("",7890))
# 变为监听套接字
tcp_sever_socket.listen(128)
while True:
# 等待连接
new_socket,client_addr = tcp_sever_socket.accept()
# 为这个客户端服务
gevent.spawn(service_client,new_socket)
tcp_sever_socket.close()
if __name__ == '__main__':
main()
单进程-单线程-非阻塞http服务器
import socket
import re
def service_client(client_socket,recv_data):
ret = re.match(r"[^/]+(/[^ ]*)",recv_data)
if ret:
ret = ret.group(1)
if ret == "/":
ret = "/index.html"
try:
with open("./html" + ret,"rb") as f:
html_content = f.read()
response = "HTTP/1.1 200 OK\r\n"
response += "Content-Length:%d\r\n\r\n" % len(html_content)
client_socket.send(response.encode("utf-8"))
client_socket.send(html_content)
except:
response = "HTTP/1.1 404 NOT FOUND\r\n\r\n"
response += "-----file not found----"
client_socket.send(response.encode("utf-8"))
def main():
# 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定套接字
tcp_server_socket.bind(("", 7890))
# 变为监听套接字
tcp_server_socket.listen(128)
# shezhi为非阻塞
tcp_server_socket.setblocking(False)
client_socket_list = list()
while True:
try:
new_socket,client_addr = tcp_server_socket.accept()
except:
pass
else:
new_socket.setblocking(False)
client_socket_list.append(new_socket)
for client_socket in client_socket_list:
try:
recv_data = client_socket.recv(1024).decode("utf-8")
except:
pass
else:
if recv_data:
service_client(client_socket,recv_data)
else:
client_socket.close()
client_socket_list.remove(client_socket)
tcp_server_socket.close()
if __name__ == '__main__':
main()
使用epoll实现http服务器
不在是轮询的方式,epoll采用事件通知的方式,效率更高,但不支持windows
import socket
import re
import select
def service_client(new_socket,request):
ret = re.match(r"[^/]+(/[^ ]*)", request)
file_name = ""
if ret:
file_name = ret.group(1)
if file_name == "/":
file_name = "/index.html"
try:
with open("./html" + file_name, "rb") as f:
html_content = f.read()
response_body = html_content
response_header = "HTTP/1.1 200 OK\r\n"
response_header += "Content-Length:%d\r\n\r\n" % len(response_body)
response = response_header.encode("utf-8")
new_socket.send(response)
new_socket.send(response_body)
except:
response = "HTTP/1.1 404 NOT FOUND\r\n"
response += "\r\n"
response += "------file not found-----"
new_socket.send(response.encode("utf-8"))
def main():
# 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定套接字
tcp_server_socket.bind(("", 7890))
# 变为监听套接字
tcp_server_socket.listen(128)
# 设置为非阻塞
tcp_server_socket.setblocking(False)
# 创建一个epoll对象
epl = select.epoll()
# 将监听套接字对应的fd注册到epoll中
epl.register(tcp_server_socket.fileno(),select.EPOLLIN)
# 定义个字典
fd_event_dict = dict()
while True:
# 默认会堵塞,直到os检测到数据到来,通过时间通知方式告诉这个程序,此时才会解堵塞
fd_event_list = epl.poll()
# (fd,event),套接字对应的文件描述符,这个文件描述符到底是什么事件,例如可以调用recv接受等
for fd,event in fd_event_list:
# 等待客户端连接
if fd == tcp_server_socket.fileno():
print("等待连接")
new_socket,client_addr = tcp_server_socket.accept()
epl.register(new_socket.fileno(),select.EPOLLIN)
fd_event_dict[new_socket.fileno()] = new_socket
elif event == select.EPOLLIN:
# 判断已连接的客户端是否有数据发来
recv_data = fd_event_dict[fd].recv(1024).decode("utf-8")
print(">>>>"*5)
print(recv_data)
if recv_data:
service_client(fd_event_dict[fd],recv_data)
else:
fd_event_dict[fd].close()
epl.unregister(fd)
del fd_event_dict[fd]
# 关闭套接字
tcp_server_socket.close()
if __name__ == '__main__':
main()