网络协议二

一、套接字Socket

基于 TCP UDP 协议的 Socket 编程,在讲 TCP 和 UDP 协议的时候,我们分客户端和服务端,在写程序的时候,我们也同样这样分。
在网络层,Socket 函数需要指定到底是 IPv4 还是 IPv6,分别对应设置为 AF_INET 和 AF_INET6。另外,还要指定到底是 TCP 还是 UDP。还记得咱们前面讲过的,TCP 协议是基于数据流的,所以设置为 SOCK_STREAM,而 UDP 是基于数据报的,因而设置为 SOCK_DGRAM。

监听的 Socket 和真正用来传数据的 Socket 是两个,一个叫作监听 Socket,一个叫作已连接 Socket

比喻:接待客人

想象你在家里准备接待客人,你有一个门铃和一个客厅。门铃相当于监听 Socket,而客厅相当于已连接 Socket。

  1. 监听 Socket(门铃)

    • 你家的门铃一直在等待有人按下它,这就像服务器上的监听 Socket 一直在等待新的连接请求。
    • 当有人按下门铃时,你知道有客人到访了,但你还不知道是谁,也还没有开始与客人交谈。
  2. 已连接 Socket(客厅)

    • 当你开门迎接客人,并带他们到客厅后,你就开始与客人交流了,这时候的客人就相当于已连接 Socket。
    • 在客厅里,你可以与每个客人进行独立的对话,不会相互干扰。

技术解释

在网络编程中,特别是 TCP 服务器程序中,监听 Socket 和已连接 Socket 是两个不同的概念和用途:

  1. 监听 Socket

    • 作用:用来监听和接受新的连接请求。
    • 创建:在服务器启动时创建,并绑定到特定的 IP 地址和端口。
    • 工作方式:服务器调用 listen() 方法,使这个 Socket 进入监听状态,等待客户端的连接请求。当有客户端请求连接时,服务器调用 accept() 方法,从监听 Socket 接受连接请求。
  2. 已连接 Socket

    • 作用:用来与客户端进行实际的数据传输。
    • 创建:当服务器调用 accept() 方法并成功接收一个客户端连接后,会生成一个新的已连接 Socket。这个 Socket 专门用于与该客户端进行通信。
    • 工作方式:服务器使用这个已连接 Socket 调用 send()recv() 方法,与客户端交换数据。

基于 TCP 协议的 Socket 程序函数调用过程

在这里插入图片描述

write() 和 read():适用于所有类型的文件描述符,包括 Socket,功能简单直接。
send() 和 recv():专为网络 Socket 设计,提供额外的功能和灵活性,通过 flags 参数控制行为。

基于 UDP 协议的 Socket 程序函数调用过程

对于 UDP 来讲,过程有些不一样。UDP 是没有连接的,所以不需要三次握手,也就不需要调用 listen 和 connect,但是,UDP 的的交互仍然需要 IP 和端口号,因而也需要 bind。UDP 是没有维护连接状态的,因而不需要每对连接建立一组 Socket,而是只要有一个 Socket,就能够和多个客户端通信。也正是因为没有连接状态,每次通信的时候,都调用 sendto 和 recvfrom,都可以传入 IP 地址和端口。
在这里插入图片描述

服务器如何接更多的项目?

会了这几个基本的 Socket 函数之后,你就可以轻松地写一个网络交互的程序了。就像上面的过程一样,在建立连接后,进行一个 while 循环。客户端发了收,服务端收了发。
当然这只是万里长征的第一步,因为如果使用这种方法,基本上只能一对一沟通。如果你是一个服务器,同时只能服务一个客户,肯定是不行的。这就相当于老板成立一个公司,只有自己一个人,自己亲自上来服务客户,只能干完了一家再干下一家,这样赚不来多少钱。
那作为老板你就要想了,我最多能接多少项目呢?当然是越多越好。
我们先来算一下理论值,也就是最大连接数,系统会用一个四元组来标识一个 TCP 连接。
{本机 IP, 本机端口, 对端 IP, 对端端口}
服务器通常固定在某个本地端口上监听,等待客户端的连接请求。因此,服务端端 TCP 连接四元组中只有对端 IP, 也就是客户端的 IP 和对端的端口,也即客户端的端口是可变的,因此,最大 TCP 连接数 = 客户端 IP 数×客户端端口数。对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。
当然,服务端最大并发 TCP 连接数远不能达到理论上限。首先主要是文件描述符限制,按照上面的原理,Socket 都是文件,所以首先要通过 ulimit 配置文件描述符的数目;另一个限制是内存,按上面的数据结构,每个 TCP 连接都要占用一定内存,操作系统是有限的。

所以,作为老板,在资源有限的情况下,要想接更多的项目,就需要降低每个项目消耗的资源数目。

方式一:将项目外包给其他公司(多进程方式)

方式二:将项目转包给独立的项目组(多线程方式)

上面这种方式你应该也能发现问题,如果每次接一个项目,都申请一个新公司,然后干完了,就注销掉这个公司,实在是太麻烦了。毕竟一个新公司要有新公司的资产,有新的办公家具,每次都买了再卖,不划算。
于是你应该想到了,我们可以使用线程。相比于进程来讲,这样要轻量级的多。如果创建进程相当于成立新公司,购买新办公家具,而创建线程,就相当于在同一个公司成立项目组。一个项目做完了,那这个项目组就可以解散,组成另外的项目组,办公家具可以共用。

上面基于进程或者线程模型的,其实还是有问题的。新到来一个 TCP 连接,就需要分配一个进程或者线程。一台机器无法创建很多进程或者线程。有个C10K,它的意思是一台机器要维护 1 万个连接,就要创建 1 万个进程或者线程,那么操作系统是无法承受的。如果维持 1 亿用户在线需要 10 万台服务器,成本也太高了。

方式三:一个项目组支撑多个项目(IO 多路复用,一个线程维护多个 Socket)

当然,一个项目组可以看多个项目了。这个时候,每个项目组都应该有个项目进度墙,将自己组看的项目列在那里,然后每天通过项目墙看每个项目的进度,一旦某个项目有了进展,就派人去盯一下。

由于 Socket 是文件描述符,因而某个线程盯的所有的 Socket,都放在一个文件描述符集合 fd_set 中,这就是项目进度墙,然后调用 select 函数来监听文件描述符集合是否有变化。一旦有变化,就会依次查看每个文件描述符。那些发生变化的文件描述符在 fd_set 对应的位都设为 1,表示 Socket 可读或者可写,从而可以进行读写操作,然后再调用 select,接着盯着下一轮的变化。。

方式四:一个项目组支撑多个项目(IO 多路复用,从“派人盯着”到“有事通知”)

上面 select 函数还是有问题的,因为每次 Socket 所在的文件描述符集合中有 Socket 发生变化的时候,都需要通过轮询的方式,也就是需要将全部项目都过一遍的方式来查看进度,这大大影响了一个项目组能够支撑的最大的项目数量。因而使用 select,能够同时盯的项目数量由 FD_SETSIZE 限制。

如果改成事件通知的方式,情况就会好很多,项目组不需要通过轮询挨个盯着这些项目,而是当项目进度发生变化的时候,主动通知项目组,然后项目组再根据项目进展情况做相应的操作。

能完成这件事情的函数叫 epoll,它在内核中的实现不是通过轮询的方式,而是通过注册 callback 函数的方式,当某个文件描述符发送变化的时候,就会主动通知。

假设进程打开了 Socket m, n, x 等多个文件描述符,现在需要通过 epoll 来监听是否这些 Socket 都有事件发生。其中 epoll_create 创建一个 epoll 对象,也是一个文件,也对应一个文件描述符,同样也对应着打开文件列表中的一项。在这项里面有一个红黑树,在红黑树里,要保存这个 epoll 要监听的所有 Socket。
当 epoll_ctl 添加一个 Socket 的时候,其实是加入这个红黑树,同时红黑树里面的节点指向一个结构,将这个结构挂在被监听的 Socket 的事件列表中。当一个 Socket 来了一个事件的时候,可以从这个列表中得到 epoll 对象,并调用 call back 通知它。

这种通知方式使得监听的 Socket 数据增加的时候,效率不会大幅度降低,能够同时监听的 Socket 的数目也非常的多了。上限就为系统定义的、进程打开的最大文件描述符个数。因而,epoll 被称为解决 C10K 问题的利器

名词解释

文件描述符限制是指一个操作系统中能够同时打开的文件和网络连接的数量上限。为了理解这个概念,我们可以先了解什么是文件描述符,然后解释为什么它会限制并发 TCP 连接数。

什么是文件描述符?

在操作系统中,每个文件(包括网络连接)在打开时,都会被分配一个唯一的标识符,这个标识符就叫做文件描述符(File Descriptor,简称 FD)。文件描述符是一个非负整数,用来引用一个打开的文件或网络连接。

  • 文件:任何类型的文件,比如文本文件、图片文件等。
  • 网络连接:TCP 连接、UDP 连接等。
  • 其他资源:如管道、设备等。

文件描述符限制

操作系统对每个进程能够同时打开的文件描述符数量有限制,这是出于资源管理和安全的考虑。这个限制通常可以分为两个层次:

  1. 软限制:用户或进程可以更改的限制,一般默认较小,但可以通过修改系统设置或在程序中动态调整。
  2. 硬限制:系统级的限制,只有管理员可以更改,通常比软限制要大。

举个例子

假设你在编写一个服务器程序,这个服务器需要处理很多客户端的连接,每个连接对应一个文件描述符。

  • 默认限制操作系统可能默认限制每个进程只能打开 1024 个文件描述符。如果你有超过 1024 个客户端同时连接到服务器,新的连接将无法建立,因为文件描述符已经用完。
  • 调整限制:你可以通过修改系统配置来增加文件描述符的限制。例如,在 Linux 系统中,你可以通过修改 /etc/security/limits.conf 文件或使用 ulimit 命令来调整这个限制。

为什么文件描述符限制会影响并发连接数?

每个 TCP 连接在服务器端都需要一个文件描述符来表示和管理。如果文件描述符用完了,服务器将无法接受新的连接,即使硬件和其他资源还能够处理更多的连接。这就导致了并发 TCP 连接数远不能达到理论上的上限。


应用层协议

二、HTTP协议:看个新闻原来这么麻烦

HTTP 是基于 TCP 协议的,要先建立 TCP 连接
建立了连接以后,浏览器就要发送 HTTP 的请求。

HTTP 请求的创建

在这里插入图片描述

第一部分:请求行

GET POST PUT DELETE
POST 往往是用来创建一个资源的,而 PUT 往往是用来修改一个资源的。

第二部分:首部字段

例如,Accept-Charset,表示客户端可以接受的字符集。防止传过来的是另外的字符集,从而导致出现乱码。

再如,Content-Type是指正文的格式。例如,我们进行 POST 的请求,如果正文是 JSON,那么我们就应该将这个值设置为 JSON。

在 HTTP 协议中,Cache-ControlIf-Modified-Since 是用于控制缓存行为和条件请求的头字段。让我们通俗易懂地解释它们的作用和工作方式。

Cache-Control 头字段用于指定缓存机制的指令,这些指令告诉浏览器和中间缓存服务器如何缓存 HTTP 响应。它可以帮助提高网站性能和减少带宽消耗。

常见指令
  1. public:响应可以被任何缓存(包括浏览器、代理服务器等)缓存。

    • 例子Cache-Control: public
  2. private:响应只能被用户的浏览器缓存,不能被共享缓存(如代理服务器)缓存。

    • 例子Cache-Control: private
  3. no-cache:缓存可以存储响应,但在使用前必须先验证其有效性(向服务器发送请求确认)。

    • 例子Cache-Control: no-cache
  4. no-store:不允许缓存响应,所有内容每次都必须从服务器获取。

    • 例子Cache-Control: no-store
  5. max-age:指定响应在缓存中可以保存的最大时间(以秒为单位),在此时间内缓存内容被认为是新鲜的。

    • 例子Cache-Control: max-age=3600(缓存内容在1小时内有效)
场景:用户访问网页
  1. 第一次访问

    • 用户浏览器向服务器请求网页。
    • 服务器返回网页内容,并在响应头中包含 Cache-Control: max-age=3600Last-Modified 头字段。
    • 浏览器将网页缓存1小时。
  2. 在1小时内再次访问

    • 浏览器检查缓存,发现缓存仍然有效(未超过 max-age)。
    • 浏览器直接从缓存中加载网页,无需向服务器发送请求。
  3. 超过1小时再次访问

    • 浏览器向服务器发送请求,包含If-Modified-Since头字段,指示上次接收到的 Last-Modified 时间。
    • 服务器检查资源是否自该时间以来有修改:
      • 如果没有修改,返回 304 Not Modified,浏览器使用缓存内容。
      • 如果有修改,返回新的网页内容和新的 Last-Modified 时间,浏览器更新缓存。

HTTP 请求的发送

就是 TCP 传输

HTTP 2.0

HTTP/2 和 HTTP/1.1 是两个版本的超文本传输协议,它们有许多不同之处,主要目的是提高性能和效率。以下是 HTTP/2 和 HTTP/1.1 的主要区别,通俗易懂地解释这些技术细节:

1. 多路复用

  • HTTP/1.1:每个请求-响应对都需要一个独立的 TCP 连接。这意味着如果一个网页上有多个资源(如图片、CSS 文件、JavaScript 文件等),每个资源的请求通常需要单独的连接,导致了“队头阻塞”(Head-of-Line Blocking)问题:一个请求阻塞了,后续请求也无法进行。
  • HTTP/2:引入了多路复用技术,多个请求和响应可以在一个单一的 TCP 连接中同时进行。这样可以有效地利用网络资源,减少延迟。

2. 二进制分帧

  • HTTP/1.1:使用纯文本格式来传输数据,包括请求和响应头部。这种格式在解析时效率较低。
  • HTTP/2:使用二进制分帧层(Binary Framing Layer),将所有传输的信息(头部和数据)编码为二进制格式。这种方式更高效、解析更快,并且更容易实现多路复用。

3. 头部压缩

  • HTTP/1.1:每次请求都会携带完整的头部信息,头部信息往往很大且包含重复的内容,浪费了带宽。
  • HTTP/2:使用 HPACK 压缩算法对头部信息进行压缩,大大减少了头部的大小和冗余信息,提高了传输效率。

4. 服务器推送

  • HTTP/1.1:只有客户端可以主动请求资源,服务器只能被动响应。
  • HTTP/2:引入了服务器推送功能,服务器可以在客户端请求某个资源时,主动推送其他相关资源到客户端,这样客户端就不需要再单独请求这些资源了。例如,当客户端请求一个 HTML 页面时,服务器可以提前推送相关的 CSS 和 JavaScript 文件。

5. 流量控制

  • HTTP/1.1:没有针对流量控制的机制,所有请求-响应对共享带宽,可能导致性能不稳定。
  • HTTP/2:引入了流量控制机制,可以更好地管理和分配带宽,确保各个请求的传输速度和效率。

6. 优先级和依赖关系

  • HTTP/1.1:没有内置的请求优先级机制,所有请求的处理顺序主要取决于到达服务器的顺序。
  • HTTP/2:允许客户端为每个请求分配优先级,并建立依赖关系,使得重要的资源可以优先传输,优化了页面加载顺序和速度。
    在这里插入图片描述

QUIC

尽管 HTTP/2 引入了多路复用技术,使得多个流可以在一个 TCP 连接上并行传输,但由于底层使用的是 TCP 协议,TCP 必须保证数据包按顺序和完整性传输。如果某个数据包出现问题,整个连接上的所有数据传输都会被阻塞,直到问题数据包被正确重传和接收。这就意味着,即使在 HTTP/2 中,某个流的数据包出现问题,其他流的数据传输也会受到影响,无法完全避免队头阻塞的问题

于是,就又到了从 TCP 切换到 UDP。这就是 Google 的 QUIC 协议

机制一:自定义连接机制

我们都知道,一条 TCP 连接是由四元组标识的,分别是源 IP、源端口、目的 IP、目的端口。一旦一个元素发生变化时,就需要断开重连,重新连接。在移动互联情况下,当手机信号不稳定或者在 WIFI 和 移动网络切换时,都会导致重连,从而进行再次的三次握手,导致一定的时延。

这在 TCP 是没有办法的,但是基于 UDP,就可以在 QUIC 自己的逻辑里面维护连接的机制,不再以四元组标识,而是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。

机制二:自定义重传机制

三、

四、

五、

六、

七、

八、

九、

十、

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

部署专属网页版ChatGPT-Next-Web

背景 工作学习中经常使用chat-gpt, 需求是多端使用gpt问答,因此搭建一个网页版本方便多个平台使用。最后选择了 ChatGPT-Next-Web 部署说明 一键部署自己的web页面,因为是使用免费的vercel托管的,vercel节点在全球都有,理论上突…

HSC Mailinspector loader.php 任意文件读取漏洞复现(CVE-2024-34470)

0x01 产品简介 HSC Mailinspector是一款远程电子邮件检查工具,支持POP3/IMAP4协议。它允许用户远程扫描最新邮件,并进行浏览、垃圾邮件排除、编辑、删除等操作,无需实际登录邮箱。 0x02 漏洞概述 由于HSC Mailinspector /public/loader.ph…

linux,lseek,append用法

打开写的.c文件 内容为 代码 <sys/stat.h> #include <fcntl.h> #include<stdio.h> #include<unistd.h> #include<string.h>//off_t lseek(int fd, off_t offset, int whence); //int open(const char *pathname, int flags); //int open(const …

【c++入门】函数重载,引用,内联函数,auto

函数重载 函数重载概念 什么是函数重载&#xff1f; 函数重载&#xff1a;是函数的一种特殊情况&#xff0c;C允许在同一作用域中声明几个功能类似的同名函数&#xff0c;这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同&#xff0c;常用来处理实现功能类似数据类…

基于鲲鹏服务器搭建简单的开源论坛系统(LAMP)实践分享

LAMPLinux apache mysql( mariadb) PHP 结合利用华为云弹性负载均衡ELB弹性伸缩AS服务 优点&#xff1a; 将访问流量自动分发到多台云服务器&#xff0c;扩展应用系统对外的服务能力&#xff0c;实现更高水平的应用容错&#xff1b; 根据不同的业务、访问需求和预设策略&…

Java编程常见问题汇总一

系列文章目录 文章目录 系列文章目录前言一、字符串连接误用二、错误的使用StringBuffer三、测试字符串相等性四、数字转换成字符串五、利用不可变对象(Immutable) 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分…

mac电脑用谷歌浏览器对安卓手机H5页面进行inspect

1、mac上在谷歌浏览器上输入 chrome://inspect 并打开该页面。 2、连接安卓手机到Mac电脑&#xff1a;使用USB数据线将安卓手机连接到Mac电脑。 3、手机上打开要的h5页面 Webview下面选择要的页面&#xff0c;点击inspect&#xff0c;就能像谷歌浏览器页面打开下面的页面&#…

大模型时代的具身智能系列专题(七)

北大王鹤团队 王鹤&#xff0c;北京大学前沿计算研究中心助理教授&#xff0c;本科毕业于清华大学&#xff0c;博士毕业于斯坦福大学&#xff0c;师从美国三院院士Leonidas. J Guibas教授。他创立并领导了具身感知与交互实验室(EPIC Lab)&#xff0c;实验室立足三维视觉感知与…

矩阵连乘问题

#include<iostream> using namespace std; #define N 7 void MatrixChain(int p[N],int n,int m[N][N],int s[N][N]) {for(int i1;i<n;i)m[i][i]0;for(int r2;r<n;r)//有多少个相乘(规模){for(int i1;i<n-r1;i){int jir-1;m[i][j]m[i][i]m[i1][j]p[i]*p[i1]*p[j…

【AREngine BUG 解决方法】无法获取有效的相机图像尺寸

近期拿了一台 华为mate20 Pro的手机&#xff0c;在运行AR示例的过程中出现了黑屏。 问题排查 SDK版本&#xff1a;com.huawei.hms:arenginesdk:3.7.0.3 定位 经排查&#xff0c;发现(ARCamera对象的相机内参) getImageDimensions()返回的图像尺寸的width和height都为0。 这…

Vue——初识组件

文章目录 前言页面的构成何为组件编写组件组件嵌套注册 效果展示 前言 在官方文档中&#xff0c;对组件的知识点做了一个很全面的说明。本篇博客主要写一个自己的案例讲解。 vue 官方文档 组件基础 页面的构成 说到组件之前&#xff0c;先大致说明下vue中页面的构成要素。 在…

太速科技-基于XC7V690T的12路光纤PCIe接口卡

基于XC7V690T的12路光纤PCIe接口卡 一、板卡概述 基于XC7V690T的12路光纤PCI-E接口卡&#xff0c;用于实现多通道高速光纤数据接收和发送&#xff0c;板卡兼容PCIe 2.0和PCIe 3.0规范&#xff0c;利用PCI-E Switch PEX 8748实现FPGA芯片与计算机的通信&#xff0c;计算机与板…

小程序内的分包与数据共享

一:数据共享 小程序内的数据共享和vue当中不一样,vue当中的vue实例可以使得所有的组件都能this.store 但是小程序它只有page对象,和组件实例对象.对于vue而言,vue实例可以使得添加的组件都有. 但是page对象页面对象,不能使得页面内部有.只能使得这个页面内能访问.vue实例,会…

数据库 mysql 的彻底卸载

MySQL卸载步骤如下&#xff1a; &#xff08;1&#xff09;按 winr 快捷键&#xff0c;在弹出的窗口输入 services.msc&#xff0c;打开服务列表。 &#xff08;2&#xff09;在服务列表中&#xff0c; 找到 mysql 开头的所有服务&#xff0c; 右键停止&#xff0c;终止对应的…

LLM主流开源代表模型

LLM主流开源大模型介绍 1 LLM主流大模型类别 随着ChatGPT迅速火爆&#xff0c;引发了大模型的时代变革&#xff0c;国内外各大公司也快速跟进生成式AI市场&#xff0c;近百款大模型发布及应用。 目前&#xff0c;市面上已经开源了各种类型的大语言模型&#xff0c;本章节我们…

特征工程技巧—Bert

前段时间在参加比赛&#xff0c;发现有一些比赛上公开的代码&#xff0c;其中的数据预处理步骤值得我们参考。 平常我们见到的都是数据预处理&#xff0c;现在我们来讲一下特征工程跟数据预处理的区别。 数据预处理是指对原始数据进行清洗、转换、缩放等操作&#xff0c;以便为…

vue3状态管理,pinia的使用

​​​​​​​状态管理 我们知道组件与组件之间可以传递信息&#xff0c;那么我们就可以将一个信息作为组件的独立状态&#xff08;例如&#xff0c;单个组件的颜色&#xff09;或者共有状态&#xff08;例如&#xff0c;多个组件是否显示&#xff09;在组件之传递&#xff0c…

大容量异步电机直接转矩(DTC)控制matlab仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; DTC简介 直接转矩控制的基本思想就是利用逆变器所产生的空间电压矢量来控制定子磁链的旋转速度&#xff0c;通过控制定子磁链的走停来改变定子磁链的平均旋转速度的大小&#xff0c;从而改变磁通角的大小进而…

【应用层】域名系统DNS

目录 1、互联网的域名结构 2、域名服务器 域名系统 DNS (Domain Name System) 是互联网使用的命名系统&#xff0c;用来把便于人们使用的机器名字转换为 IP 地址&#xff0c;域名系统其实就是名字系统。 互联网的域名系统 DNS 被设计成为一个联机分布式数据库系统&#xff0c…

使用 zxing 生成二维码以及条形码

需求背景 前期在做项目的时候&#xff0c;有一个需求是说要生成一张条形码&#xff0c;并且呢将条形码插入到 excel 中去&#xff0c;但是之前一直没有搞过找个条形码或者是二维码&#xff0c;最后是做出来了&#xff0c;这里呢就先看看怎么生成&#xff0c;后面再抽时间来写写…