zoukankan      html  css  js  c++  java
  • http服务器长连接

    短连接是客户端每请求一个资源就需要进行tcp的三次握手和四次挥手,长连接是一次握手连接后,只要不断开连接,中间可多次发送数据,客户端和服务器频繁握手和挥手需要占用大量的网络资源,于是客户端和服务器之间的连接由短连接演变为长连接

    长连接需要在服务器返回数据的http头部增加一个Content-Length属性,告诉客户端,你本次请求的这个资源的数据长度是多少,这样,客户端在收到服务器的回应后,就可以知道我要的数据服务器是否全部给我了,如果没有,那就等待,直到服务端把全部数据发送过来。

    有了Content-Length属性,客户端和服务端一旦连接之后就不必着急着断开,因为只要客户端根据Content-Length判断本次请求的数据传输完毕,就可以接着发送另一个请求,这就实现了一次连接,多次请求,这也是长连接的优势所在了,减少了每次请求每次都要连接的冗余

    一个场景就是,浏览器打开一个网页,只需要发起一次连接请求即可,之后无论是加载图片请求还是js文件请求,都可以在一个连接中完成,而不需要每加载一个文件就发起一次请求,大大减少了连接次数,节省了网络资源。对于服务端来说也有很大的好处,因为一次连接意味着需要创建一个新的套接字,如果使用短连接,那么加载一个资源就得创建很多个套接字,资源浪费很大。

    import re
    
    
    def handle_request(handle_socket, request):
    
        print(request)
    
        request_lines = request.splitlines()
    
        # 解析 GET / HTTP/1.1
        ret = re.match(r"[^/]+/([^ ]*)", request_lines[0])
        if ret:
            file_name = ret.group(1)
        else:
            file_name = "index.html"
    
        try:
            f = open(".html\" + file_name, "rb")
        except Exception:
            response_body = "您访问的页面不存在".encode("utf8")
        else:
            html_content = f.read()
            f.close()
            response_body = html_content
    
        response_header = "HTTP/1.1 200 OK
    "
        response_header += "Content-Length:%s
    " % len(response_body)  # 浏览器接收到这么多数据就明白本次请求完成,发送下个请求
        response_header += "
    "
        response = response_header.encode("utf8") + response_body
        handle_socket.send(response)
        # handle_socket.close() 这个不要加,否则就变成短连接了
    
    
    def main():
        import socket
    
        tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        tcp_socket.bind(("", 7777))
    
        tcp_socket.listen(128)
    
        tcp_socket.setblocking(False)
    
        new_socket_list = list()
    
        while True:
    
            try:
                new_socket, new_addr = tcp_socket.accept()
            except Exception as e:
                pass
            else:
                new_socket.setblocking(False)
                new_socket_list.append(new_socket)
                print("接收到请求")
    
            for socket in new_socket_list:
                try:
                    recv_data = socket.recv(1024).decode("utf8")
                except Exception as e:
                    pass
                else:
                    if recv_data:
                        handle_request(socket, recv_data)
                    else:  # recv_data为空,说明客户端调用了close,此时该socket全部数据接收完毕,应从列表移除
                        socket.close()
                        new_socket_list.remove(socket)
    
        tcp_socket.close()
    
    
    if __name__ == "__main__":
        main()
  • 相关阅读:
    利用WinCE的精准计时函数来输出pwm信号以便控制舵机
    leafletjs旋转marker
    centos7 NodeJs安装问题:Error: Cannot find module '../lib/utils/unsupported.js'
    Django 自定义存储上传文件的文件名
    后端开发不会前端之表格插件的使用
    Django项目部署之sqlite版本升级
    SQL 循环30日
    SSRS 报表 报表迁移
    SQL SERVER中求上月、本月和下月的第一天和最后一天
    SSRS 报表 日期类表达式
  • 原文地址:https://www.cnblogs.com/olivertian/p/12612468.html
Copyright © 2011-2022 走看看