1 短连接

HTTP/1.0 及以前的版本采用的都是短连接
image.png

2 长连接

HTTP/1.1 采用的都是长连接
image.png

不用gevent, 实现单进程,单线程,长连接,且能并发处理多个浏览器请求的http服务器
核心原理:new_socket.setblocking(False)把套接字设为非阻塞

  1. from socket import *
  2. import re
  3. def serve_client(client_socket, request):
  4. request_lines = request.splitlines()
  5. print(request_lines)
  6. file_name = ""
  7. ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
  8. if ret:
  9. file_name = ret.group(1)
  10. if file_name == "/":
  11. file_name = "/index.html"
  12. try:
  13. f = open("./html"+file_name, "rb")
  14. except:
  15. response = "HTTP/1.1 404 NOT FOUND\n\n"
  16. response += "-----file not fonund-----"
  17. client_socket.send(response.encode("utf-8"))
  18. else:
  19. response_body = f.read()
  20. f.close()
  21. response_header = "HTTP/1.1 200 OK\n"
  22. response_header += "Content-Length:{}\n".format(len(response_body))
  23. response_header += "\n"
  24. response = response_header.encode("utf-8") + response_body
  25. client_socket.send(response)
  26. if __name__ == "__main__":
  27. tcp_socket = socket(AF_INET, SOCK_STREAM)
  28. tcp_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  29. tcp_socket.bind(("", 7890))
  30. tcp_socket.listen(128)
  31. tcp_socket.setblocking(False)
  32. client_socket_list = list()
  33. while True:
  34. try:
  35. new_socket, client_addr = tcp_socket.accept()
  36. except Exception as e:
  37. pass
  38. else:
  39. new_socket.setblocking(False)
  40. client_socket_list.append(new_socket)
  41. for client_socket in client_socket_list:
  42. try:
  43. recv_data = client_socket.recv(1024).decode("utf-8")
  44. except Exception as e:
  45. pass
  46. else:
  47. if recv_data:
  48. serve_client(client_socket, recv_data)
  49. else:
  50. client_socket.close()
  51. client_socket_list.remove(client_socket)
  52. tcp_socket.close()