〖Web全栈开发③〗—HTTP协议和静态web服务器

news2024/11/27 8:45:59

HTTP协议和静态web服务器

  • (一)三次握手和四次挥手
  • (二)HTTP协议
      • 2.1 HTTP协议的定义
      • 2.2 HTTP协议的组成
  • (三)搭建python自带静态web服务器
      • 3.1 静态web服务器是什么
      • 3.2 如何搭建python自带的静态web服务器
      • 3.3 访问本地的静态文件
      • 3.4 查看浏览器和搭建的web静态服务器的通信过程
  • (四)静态web服务器-返回固定页面数据
      • 4.1 开发自己的静态web服务器
      • 4.2 返回固定页面数据的代码示例
  • (五) 静态web服务器-返回指定页面数据
      • 5.1 静态web服务器的问题
      • 5.2 返回指定页面数据的代码示例
        • 丢包、粘包问题解决思路和方法
        • 发送接收缓冲 消息格式定义

🏘️🏘️个人简介:以山河作礼。
🎖️🎖️:Python领域新星创作者,CSDN实力新星认证,阿里云社区专家博主
🎁🎁:Web全栈开发专栏:《Web全栈开发》免费专栏,欢迎阅读!


(一)三次握手和四次挥手

TCP (Transmission Control Protocol) 是在互联网协议(IP)上的一种基于连接(面向连接)的传输层协议。数据通信的基本要素包括“所传输的数据”“发送方”“接收方“三个要素,还有保证所传输的数据是完好无损,正确无误的。这一普遍要求都是由TCP满足的,下面介绍TCP的三次握手和四次挥手过程。

在这里插入图片描述

三次握手:

1.客户端发送一个SYN,表示要发起一个连接请求。

2.服务端收到客户端请求之后,向客户端发送一个SYN和ACK,表示确认收到请求并准备好连接。

3.客户端接收到服务端的响应之后,向服务端发回ACK,表示确认可以建立连接了。

这个时候客户端和服务端就建立起了连接,可以开始通信了。

四次挥手:

1.客户端发送一个FIN,表示要释放连接。

2.服务端接收到FIN之后,会回复一个ACK,表示确认收到。

3.服务端准备释放连接时,同样发送一个FIN给客户端。

4.客户端接收到服务端的FIN之后,会回复一个ACK,表示确认收到释放请求。

这个时候,客户端和服务端都释放了连接,连接断开。

总结:

1.三次握手是建立TCP连接的必要步骤,而四次挥手则是释放TCP连接的必要步骤。

2.三次握手和四次挥手的目的是确保数据传输的可靠性和正确性。

3.连接的释放过程比连接的建立过程要复杂,这是因为连接释放过程需要双方都知道连接已经释放,而连接建立过程只需要被请求方知道即可。

4.TCP协议的三次握手和四次挥手是TCP协议可靠性的重要保证,也是网络通信的必要约定。

(二)HTTP协议

在这里插入图片描述

2.1 HTTP协议的定义

  • 网络协议

    • 网络协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则。
  • HTTP协议=

    • HTTP协议(超文本传输协议)是一种网络通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。默认端口:80
  • HTTPS协议

    • HTTPS协议是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。默认端口:443
  • HTTP协议的主要特点

    • 支持客户/服务器模式
    • 简单快速:客户向服务器发送请求时,只需传送请求方法和路径。请求方法常用的有GET、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
    • 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
    • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
    • 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
  • HTTPS协议的主要特点

    • 内容加密:采用混合加密技术,中间者无法直接查看明文内容。
    • 验证身份:通过证书认证客户端访问的是自己的服务器。
    • 保护数据完整性:防止传输的内容被中间人冒充或者篡改。
    • SSL证书需要购买申请,功能越强大的证书费用越高。
    • SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
    • HTTPS连接缓存不如HTTP高效,流量成本高。
    • HTTPS协议握手阶段比较费时,对网站的响应速度有影响,影响用户体验。

2.2 HTTP协议的组成

在这里插入图片描述

  • 请求行

    • 请求行由请求方法字段(GET/POST)、URL字段和HTTP协议版本组成。
  • URL字段

    • URL字段也称为请求地址
  • HTTP协议的请求方法

    • HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。
    • 常用的方法:
      • GET方法:浏览器的地址栏中输入网址的方式访问网页时,浏览器采用GET方法向服务器获取资源。
      • POST方法:要求被请求服务器接受附在请求后面的数据,常用于提交表单。
  • GET和POST区别

    • 从参数的传递方面来看,GET请求的参数是直接拼接在地址栏URL的后面,而POST请求的参数是放到请求体里面的;
    • 从长度限制方面来看,GET请求有具体的长度限制,一般不超过1024KB,而POST理论上没有,但是浏览器一般都有一个界限;
    • 从安全方面来看,GET请求相较于POST,因为数据都是明文显示在URL上面的,所以安全和私密性不如POST;
    • 从本质上来说,GET和POST都是TCP连接,并无实质的区别.但是由于HTTP/浏览器的限定,导致它们在应用过程中体现出了一些不同.GET产生一个数据包,POST产生两个数据包.对于GET请求,浏览器会把http header 和 data 一并发出去,服务器响应200(返回数据).而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200
  • 请求头部

    • 请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号 “ : ” 分隔。

    • 请求头部通知服务器有关于客户端请求的信息,典型的请求头有:

      • User-Agent:产生请求的浏览器类型。

      • Accept:客户端可识别的内容类型列表。

    • Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。

      • Content-Type:请求体的MIME类型。MIME类型:描述消息内容类型的因特网标准,常见的有application/json、image/jpeg、application/octet-stream等。

**加粗样式
**

  • 请求正文

    • 请求正文向服务器提交的请求数据,GET请求的参数一般是放在请求行后的键值对,post请求的参数类型多样(表单、json、xml、图片等)

    • 响应行

    • 响应行由响应状态码、响应信息和HTTP协议版本字段3个字段组成

    • 响应状态码

    • 响应状态码由三位数字组成,第一个数字定义了响应的类别,且有五种类型

      • 1xx:指示信息–表示请求已接收,继续处理
      • 2xx:成功–表示请求已被成功接收、理解、接受
      • 3xx:重定向–要完成请求必须进行更进一步的操作
      • 4xx:客户端错误–请求有语法错误或请求无法实现
      • 5xx:服务器端错误–服务器未能实现合法的请求
  • 常见的响应状态码

    • 200 - 请求成功,已经正常处理完毕
    • 301 - 请求永久重定向,转移到其它URL
    • 302 - 请求临时重定向
    • 304 - 请求被重定向到客户端本地缓存
    • 400 - 客户端请求存在语法错误
    • 401 - 客户端请求没有经过授权
    • 403 - 客户端的请求被服务器拒绝,一般为客户端没有访问权限
    • 404 - 客户端请求的URL在服务端不存在
    • 500 - 服务端永久错误
    • 503 - 服务端目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
  • 响应头

    • 响应头用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会儿它回送的数据。

    • 常见的响应头:

      • Content-Length:表示内容长度

      • Content- Type:表示后面的文档属于什么MIME类型

      • Server:服务器通过这个头告诉浏览器服务器的类型

在这里插入图片描述

  • 响应正文

    • 响应正文就是响应的消息体,如果是纯数据就是返回纯数据,如果请求的是HTML页面,那么返回的就是HTML代码,如果是图片就是图片等。

(三)搭建python自带静态web服务器

3.1 静态web服务器是什么

静态web服务器是指可以为出发请求的浏览器提供静态文档的程序。

平时我们浏览百度新闻数据的时候,每天的新闻数据都会发生变化,那访问的这个页面就是动态的。

而静态的Web服务器,页面的数据不会发生变化。

3.2 如何搭建python自带的静态web服务器

搭建python自带的静态web服务器使用命令:

python -m http.server

  • -m:表示运行包里面的模块,执行这个命令时,需要进入指定静态文件的目录,然后通过浏览器就能访问对应的html文件

  • 端口号不指定默认是8000

  • 搭建步骤

    • 在终端首先进入到指定静态文件的目录

    • 输入命令:python -m http.server [端口号] --bind 127.0.0.1,不指定端口号的话默认是8000

在这里插入图片描述

3.3 访问本地的静态文件

在浏览器中访问本地的html文件

首先在命令行进入该文件所在目录,然后启动静态服务器:

在这里插入图片描述

最后可以在浏览器进行访问

在这里插入图片描述

3.4 查看浏览器和搭建的web静态服务器的通信过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgarB0u4-1684031530571)(imgs\1677141611914.png)]

在这里插入图片描述

(四)静态web服务器-返回固定页面数据

4.1 开发自己的静态web服务器

  • 实现步骤
    • 编写一个TCP服务端程序。
    • 获取浏览器发送的http请求报文数据。
    • 读取固定页面数据,把页面数据组装成HTTP响应数据发送给浏览器。
    • HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字。

4.2 返回固定页面数据的代码示例

import socket


if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用, 程序退出端口立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定端口号
    tcp_server_socket.bind(("", 9000))
    # 设置监听
    tcp_server_socket.listen(128)
    while True:
        # 等待接受客户端的连接请求
        new_socket, ip_port = tcp_server_socket.accept()
        # 代码执行到此,说明连接建立成功
        recv_client_data = new_socket.recv(4096)
        # 对二进制数据进行解码
        recv_client_content = recv_client_data.decode("utf-8")
        print(recv_client_content)

        with open("static/index.html", "rb") as file:
            # 读取文件数据
            file_data = file.read()


        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_header = "Server: PWS1.0\r\n"
        # 响应体
        response_body = file_data

        # 拼接响应报文
        response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
        # 发送数据
        new_socket.send(response_data)

        # 关闭服务与客户端的套接字
        new_socket.close()

(五) 静态web服务器-返回指定页面数据

5.1 静态web服务器的问题

目前的web服务器,不管用户访问什么页面,返回的都是固定页面的数据,接下来需要根据用户的请求返回指定页面的数据

返回指定页面数据的实现步骤:

  1. 获取用户请求资源的路径。
  2. 根据请求资源的路劲,读取指定文件的数据。
  3. 组装指定文件数据的响应报文,发送给浏览器。
  4. 判断亲贵的文件在服务端不存在,组装404状态的响应报文,发送给浏览器。

5.2 返回指定页面数据的代码示例

import socket


def main():
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用, 程序退出端口立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定端口号
    tcp_server_socket.bind(("", 9000))
    # 设置监听
    tcp_server_socket.listen(128)
    while True:
        # 等待接受客户端的连接请求
        new_socket, ip_port = tcp_server_socket.accept()
        # 代码执行到此,说明连接建立成功
        recv_client_data = new_socket.recv(4096)
        if len(recv_client_data) == 0:
            print("关闭浏览器了")
            new_socket.close()
            return

        # 对二进制数据进行解码
        recv_client_content = recv_client_data.decode("utf-8")
        print(recv_client_content)
        # 根据指定字符串进行分割,最大分割次数指定2
        request_list = recv_client_content.split(" ", maxsplit=2)
        # print("===")
        # print(request_list)
        # print("===")

        # 获取请求资源路径
        request_path = request_list[1]
        print(request_path)

        # 判断请求的是否是根目录,如果条件成立,指定首页数据返回
        if request_path == "/":
            request_path = "/index.html"

        try:
            # 动态打开指定文件
            with open("static" + request_path, "rb") as file:
                # 读取文件数据
                file_data = file.read()
        except Exception as e:
            # 请求资源不存在,返回404数据
            # 响应行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            # 响应头
            response_header = "Server: PWS1.0\r\n"
            with open("static/error.html", "rb") as file:
                file_data = file.read()
            # 响应体
            response_body = file_data

            # 拼接响应报文
            response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
            # 发送数据
            new_socket.send(response_data)
        else:
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_header = "Server: PWS1.0\r\n"

            # 响应体
            response_body = file_data

            # 拼接响应报文
            response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
            # 发送数据
            new_socket.send(response_data)
        finally:
            # 关闭服务与客户端的套接字
            new_socket.close()


if __name__ == '__main__':
    main()

丢包、粘包问题解决思路和方法

问题:

Socket有一个缓冲区,缓冲区是一个流,先进先出,发送和取出都可以自定义大小,如果缓冲区的数据未取完,则可能会存在数据堆积。其中recv(1024)表示从缓冲区里取最大为1024个字节,但实际取值大小是不确定的,可能会导致丢包,socket发送两条连续数据时,也有可能最终会拼接成一条进行发送,所以也会导致粘包问题的产生。

解决的一些办法和思路:

在每条数据发送之间增加停顿时间,如【tiem.sleep(0.5) # 延时0.5s】

每次发送后等待对方确认接收数据,确认完毕后再发送下一条(加验证),否则重传

减少一次性发送和接收数据的大小,理论上buffer size越小丢包或粘包率就越低,建议在1024~10240之间

发送接收缓冲 消息格式定义

编程的时候,如果要跟某个IP建立连接,我们需要调用操作系统提供的 socket API。

socket 在操作系统层面,可以理解为一个文件。我们可以对这个文件进行一些方法操作。

用listen方法,可以让程序作为服务器监听其他客户端的连接。
用connect,可以作为客户端连接服务器。
用send或write可以发送数据,recv或read可以接收数据。
在建立好连接之后,如果我们想给远端服务发点什么东西,那就只需要对这个文件执行写操作就行了。

剩下的发送工作自然就是由操作系统内核来完成了。

既然是写给操作系统,那操作系统就需要提供一个地方给用户写。同理,接收消息也是一样。这个地方就是 socket 缓冲区。

用户发送消息的时候写给 send buffer(发送缓冲区)
用户接收消息的时候写给 recv buffer(接收缓冲区)
也就是说一个socket ,会带有两个缓冲区,一个用于发送,一个用于接收。因为这是个先进先出的结构,有时候也叫它们发送、接收队列。

在企业中开发的程序通信,消息往往有格式定义。消息的格式定义可以归入OSI中的表示层

比如:定义的消息,包括消息头和消息体。

消息头存放消息的数据格式(消息的长度、类型、状态等),消息体存放具体传送的数据。

对于TCP协议传输信息的程序来说,格式一定要有明确规定的消息边界。因为TCP传输的是字节流(bytes stream),如果消息中没有指定边界或者长度,接收方就不知道完整的消息从字节流的哪里开始,到哪里结束。

指定消息的边界有两种方式:

1.用特殊字节作为消息的结尾符号

可以用消息中不易出现的字符串(比如 FFFFFF)作为消息的结尾字符

2.在消息开头某个位置,直接指定消息的长度

UDP协议通常不用指定边界,因为UDP是数据报协议,应用程序从socket接收到的

必定是发送方发送的完整消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/533571.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【栈和队列】的特性以及基本接口的实现

目录 一、栈 1.1 栈的概念 1.2 栈的接口实现 二、队列 2.1 队列的概念 2.2 队列的接口实现 2.3 栈和队列的区别 三、栈和队列LeetCode练习 3.1 力扣_232.用栈实现队列 3.2 力扣_225.用队列实现栈 3.3 力扣_622.设计循环队列 3.4 力扣_20.有效的括号 一、栈 第一次学…

电容在电路中的作用

电容、也称为电容器,字面意思理解就是一种“装电的容器”,是一种容纳电荷的器件。它拥有两个电极板,由两个电极板及其中间所夹的介质封装而成。 常用电容极性判断:   铝电解电容:长脚为正极,短脚为负极&…

【MySQL学习】MySQL索引特性

文章目录 一、初识MySQL索引1.1 MySQL索引的概念1.2 MySQL索引的作用 二、MySQL的数据存储2.1 MySQL存储与磁盘之间的关系2.2 MySQL与磁盘交互的基本单位2.3 认识数据页Page 三、索引的理解3.1 测试案例3.2 探究单个和多个Page存储数据时的情况3.3 页目录3.4 为什么InooDB存储引…

《面试1v1》CAS

我是 javapub,一名 Markdown 程序员从👨‍💻,八股文种子选手。 面试官: 上个面试官对你的基础有了一定了解,听说你小子很不错!下面我们聊点有深度的。 面试官: 简单介绍下 CAS 你了…

10款Photoshop免费在线工具推荐

AdobePhotoshop下载繁琐,付费昂贵,让很多设计师望而却步! 经过几个小时的筛选和测试,筛选出10款Photoshop免费在线工具,与Photoshop一样强大。让我们看看! 1.即时设计 智能抠图 当我们想要去重图片背景&…

【鲁棒优化、机会约束】具有分布鲁棒联合机会约束的能源和储备调度研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

JAVA中的深情哥-Exception(异常)-上

文章目录 目录 文章目录 前言 一,Exception的起源 二,异常类 三,自定义异常 总结 前言 大家好,我是最爱吃兽奶,今天给大家介绍一下java中的深情哥 - Exception 秋风依依秋水寒,一点离愁两黯然;今生默默唯轻舞&a…

抖音林客系统开发

抖音林客系统是一款基于AI技术的推荐算法系统,主要应用于抖音平台中用户的内容推荐和个性化服务。开发抖音林客系统需要掌握以下关键技术: 数据采集与处理:需要对海量的用户数据进行采集和处理,包括用户的观看历史、互动行为、…

K-Village NFT 作品集

K-Village 是韩国领先的娱乐公司和 Cube 娱乐公司所拥有的空间,引领了元宇宙行业的发展。在这个虚拟的「韩国村」中,可以参观代表韩国文化的韩国公司和品牌。 此外,这个系列的购买者还将获得特别奖励!如果你刚好拥有 20 个 K-Vill…

不懂Spring IOC?你可能已经OUT了!快来了解它的奥秘!

大家好,我是小米,一个热衷于技术分享的小伙伴。今天,我想和大家聊一聊Spring IoC(Inversion of Control)的理解、原理与实现。对于使用Spring框架的开发者来说,IoC容器是一个非常重要的概念,它帮…

C++ ---- 日期类实现+阅读文档(文档可直接下载)

日期类文档下载(日期类详细介绍) word文档 MyDate/MyDate/日期类阅读文档.docx 张喜阳/进阶代码仓库 - Gitee.comhttps://gitee.com/niuniuzxy/advanced-code-warehouse/blob/a25baeee2bd0f0c64f96315bb0d0023308329d92/MyDate/MyDate/%E6%97%A5%E6%9C%9F%E7%B1%BB%E9%98%85…

十六、Config分布式配置中心

目录 分布式配置中心概述 1、为什么需要分布式配置中心? 2、配置中心的作用: Spring Cloud Config简介 新建项目springcloud-config-server 1、引入配置中心config-server的依赖 2、在github/gitee上新建一个远程仓库作为config的远程配置中心 3、…

3年测试技术面一题都看不懂,字节面试真的变态.....

最近我的一个读者朋友去了字节面试,来给我发信息吐槽,说字节的面试太困难了,像他这种三年经验的测试员,在技术面,居然一题都答不上来,这要多高的水平才能有资格去面试字节的测试岗位。 确实,字…

Vue2+CSS实现一个瀑布流布局案例

在练习代码的时候,看到了携程的首页下方的布局还挺好看 就是一个瀑布流的布局效果,在携程上是一共两列布局,然后每个格子的高度都会根据图片的高度做排布 一开始是想使用flex进行布局,先让每个格子各占百分之49,然后贴…

微信小程序实现电子书搜索与下载

1、背景 自己已经做了一版电子书下载网站(走蛟电子书),但用户使用手机更方便些,为改善用户体验,准备做一款微信小程序实现电子书搜索与下载的功能。 2、技术栈 由于功能较为单一,因此前端使用原生的微信…

CSS基础语法

CSS基础语法知识 文章目录 CSS基础语法1. CSS的引入方式1.1 内部样式1.2 外部样式1.3 内联样式 2. CSS标签选择器2.1 标签选择器2.2 类选择器2.3 id选择器2.4 复合选择器 3. CSS常见属性3.1 字体相关3.2 文本相关3.3 颜色的写法3.4 背景相关3.5 边框相关3.6 元素的显示模式3.7 …

【链表应用】| 一元多项式的操作

目录 一. 🦁 要求:二. 代码实现(Java & c)1. Java实现2.C语言实现 三. 🦁 总结 一. 🦁 要求: 设有两个一元多项式: p(x)p0p1xp2x2pnxn q(x)q0q1xq2x2qmxm 多项式项的系数为实数,指数为整数&#xff0c…

11个免费的数据可视化工具推荐

数据可视化之所以流行,不仅是因为它简化了我们查看复杂数据的方式,更是因为数据可视化可以加快我们获取数据信息的速度。 本文专门为您列出了11个免费的数据可视化工具,帮助您快速掌握数据可视化技能。 1.即时设计 即时设计是可云端编辑的…

物通博联工业物联网解决方案,助力工厂实现设备远程运维

各类设备制造工厂随着经营规模与业务的扩张,设备可以销往全国各地甚至是全球,是工厂实力的体现。当设备越来越多、分布越来越广,设备管理的工作量和成本直线上升,可能面对维护不及时的情况,影响到客户经济效益和对工厂…

spark源码 spark on yarn环境的创建

1.入口类 sparkSubmit 的main方法 提交application submitnew SparkSubmit submit.doSubmit(args) -> super.doSubmit(args): parseArguments(args) :参数解析 方法 中 new sparkSubmitArguments(args) 点进去该类(主要解析参数),然后找到parse&am…