单进程单线程实现多并发
原理:将套接字设置为不阻塞,让它一直在循环,当有客户端连接,就将它添加到列表中,随后继续循环
import socket
socket_list = list()
def service_client(new_socket, request):
"""为这个客户端返回数据"""
# GET / HTTP/1.1
# .....
file_list = request.splitlines()
print("*" * 50)
ret = re.match(r"[^/]+(/[^ ]*)", file_list[0])
if ret:
file_name = ret.group(1)
else:
pass
# 准备发送给浏览器的数据
try:
# 返回http格式的数据
# 准备发送给浏览器的数据---header
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
f = open("./html" + file_name, "rb")
html_content = f.read()
except:
response = "HTTP/1.1 404 NOTFOUND\r\n"
response += "\r\n"
html_content = "-----file not found-------"
# 将header发送给浏览器
new_socket.send(response.encode("utf-8"))
# 将内容发过去
new_socket.send(html_content)
else:
# 将header发送给浏览器
new_socket.send(response.encode("utf-8"))
# 将内容发过去
new_socket.send(html_content)
def main():
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server.bind(("", 7788))
tcp_server.listen(128)
# 设置tcp_server套接字为不阻塞
tcp_server.setblocking(False)
while True:
try:
new_socket, client_addr = tcp_server.accept()
# 没有客户端连接就会出现异常
except Exception as ret:
print("------没有客户端连接-------")
else:
print("------有客户端连接-------")
# 设置new_socket套接字为不阻塞
new_socket.setblocking(False)
socket_list.append(new_socket)
for socket_temp in socket_list:
try:
rev_data = socket_temp.recv(1024)
# 没有数据发送就会出现异常
except Exception as ret:
print("------没有数据发送过来-------")
else:
if rev_data:
service_client(socket_temp, rev_data)
else:
# 如果接受到数据,且数据为空,说明客户端已经调用了close()
socket_temp.close()
socket_list.remove(socket_temp)
print("已经关闭")
if __name__ == "__main__":
main()
因为上面的程序,等数据发送完之后,就将socket关闭了,所以还是短链接实现的
要想将连接变为长连接,就不能关闭连接。
所以我们在发送数据时,需要加上Content-Length:包体长度
这样浏览器得到数据,就不会等待了
response_body = html_content
response_header = "HTTP/1.1 200 OK\r\n"
# 将文件长度发送过去,浏览器得到数据,就不会再等待,可以实现长连接
response += "Content-Length:%d\r\n" % len(response_body)
response += "\r\n"