前言
需要知道的以下几点:
- 项目需求:浏览器作为客户端发送请求,服务器接收并处理返回对应的数据–也就是html文档。
- 部分重复代码并未定义函数,直接复制粘贴。
- epoll中重要的是“事件通知”和“内存映射”以及“fd(file descriptor)”的灵活使用。
- 此文中还有长连接的运用及介绍。
代码部分
import socket, re, gevent
import select
from gevent import monkey
def service_client(client_socket,client_request):
client_request_lines = client_request.splitlines()
print(">>" * 20)
print(client_request_lines)
ret = re.match(r"[^/]+(/[^ ]*)", client_request_lines[0])
file_name = ""
if ret:
file_name = ret.group(1)
if file_name == "/":
file_name = "/index.html"
try:
f = open("./html" + file_name, "rb")
html_content = f.read()
f.close()
response_body = html_content
response_header = "HTTP/1.1 200 OK\r\n"
response_header += "Content-Length:%d\r\n" % len(response_body)
response_header += "\r\n"
response = response_header.encode("gbk")+response_body
client_socket.send(response)
except Exception as a:
f = open("./html/" + "404.html", "rb")
html_content = f.read()
f.close()
response_body = html_content
response_header = "HTTP/1.1 200 OK\r\n"
response_header += "Content-Length:%d\r\n" % len(response_body)
response_header += "\r\n"
response = response_header.encode("gbk") + response_body
client_socket.send(response)
pass
def main():
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp_socket.bind(("192.168.233.1", 7890))
tcp_socket.listen(128)
tcp_socket.setblocking(False)
epl = select.epoll()
epl.register(tcp_socket.fileno(),select.EPOLLIN)
fd_event_dict = dict()
while True:
fd_event_list = epl.poll()
for fd, event in fd_event_list:
if fd == tcp_socket.fileno():
client_socket, client_addr = tcp_socket.accept()
epl.register(client_socket.fileno(), select.EPOLLIN)
fd_event_dict[client_socket.fileno()] = client_socket
elif event == select.EPOLLIN:
recv_data = fd_event_dict[fd].recv(1024).decode("utf-8")
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_socket.close()
pass
if __name__ == '__main__':
main()
补充
- win上没有epoll
- epoll的实现思想口语化理解:我不非堵塞了,循环问你有没有事还是浪费资源,你自己来吧,当你有什么事的时候你肯定会告诉我的,你要是想链接我,那么fd肯定是监听套接字的,你要是发信息给我,要么是有数据的,我就接受,要么是没数据的,我就关闭你了。
- 长连接的意义:减少使用服务器的资源。一次性要所有的数据:(比如一次性将网页中的图片全部要来(可能比起短连接的要慢一点【短链接中服务器解析浏览器的数据请求中包含多个图片文件,会建立多个短链接发送数据】–但是现在网速都相对较快了,所以在资源合理化利用的角度上来说是要使用长连接的)