HTTP第三讲——四层模型、七层模型

四层模型

TCP/IP 协议,它是 HTTP 协议的下层协议,负责具体的数据传输
工作。TCP/IP 协议是一个“有层次的协议栈”。
TCP/IP 当初的设计者真的是非常聪明,创造性地提出了“分层”的概念,把复杂的网络通信划分出多个层次,再给每一个层次分配不同的职责,层次内只专心做自己的事情就好,用“分而治之”的思想把一个“大麻烦”拆分成了数个“小麻烦”,从而解决了网络通信的难题。
在这里插入图片描述
TCP/IP 协议总共有四层,就像搭积木一样,每一层需要下层的支撑,同时又支撑着上层,任何一层被抽掉都可能会导致整个协议栈坍塌。

第一层叫“链接层”(link layer),负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标记网络上的设备,所以有时候也叫 MAC 层。
第二层叫“网际层”或者“网络互连层”(internet layer),IP 协议就处在这一层。因为 IP协议定义了“IP 地址”的概念,所以就可以在“链接层”的基础上,用 IP 地址取代 MAC 地址,把许许多多的局域网、广域网连接成一个虚拟的巨大网络,在这个网络里找设备时只要把IP 地址再“翻译”成 MAC 地址就可以了。
第三层叫“传输层”(transport layer),这个层次协议的职责是保证数据在 IP 地址标记的两点之间“可靠”地传输,是 TCP 协议工作的层次,另外还有它的一个“小伙伴”UDP。
TCP 是一个有状态的协议,需要先与对方建立连接然后才能发送数据,而且保证数据不丢失不重复。而 UDP 则比较简单,它无状态,不用事先建立连接就可以任意发送数据,但不保证数据一定会发到对方。两个协议的另一个重要区别在于数据的形式。TCP 的数据是连续的“字节流”,有先后顺序,而 UDP 则是分散的小数据包,是顺序发,乱序收。
第四层叫“应用层”(application layer),由于下面的三层把基础打得非常好,所以在这一层就“百花齐放”了,有各种面向具体应用的协议。例如 Telnet、SSH、FTP、SMTP 等等,当然还有我们的 HTTP。
MAC 层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段(segment),HTTP 的传输单位则是消息或报文(message)。但这些名词并没有什么本质的区分,可以统称为数据包。

七层模型

TCP/IP 发明于 1970 年代,当时除了它还有很多其他的网络协议,整个网络世界比较混乱。
这个时候国际标准组织(ISO)注意到了这种现象,感觉“野路子”太多,就想要来个“大一统”。于是设计出了一个新的网络分层模型,想用这个新框架来统一既存的各种网络协议。
OSI 模型分成了七层,部分层次与 TCP/IP 很像,从下到上分别是:在这里插入图片描述

  1. 第一层:物理层,网络的物理形式,例如电缆、光纤、网卡、集线器等等;
  2. 第二层:数据链路层,它基本相当于 TCP/IP 的链接层;
  3. 第三层:网络层,相当于 TCP/IP 里的网际层;
  4. 第四层:传输层,相当于 TCP/IP 里的传输层;
  5. 第五层:会话层,维护网络中的连接状态,即保持会话和同步;
  6. 第六层:表示层,把数据转换为合适、可理解的语法和语义;
  7. 第七层:应用层,面向具体的应用传输数据。

两个分层模型的映射关系

在这里插入图片描述

  1. 第一层:物理层,TCP/IP 里无对应;
  2. 第二层:数据链路层,对应 TCP/IP 的链接层;
  3. 第三层:网络层,对应 TCP/IP 的网际层;
  4. 第四层:传输层,对应 TCP/IP 的传输层;
  5. 第五、六、七层:统一对应到 TCP/IP 的应用层。

所谓的“四层负载均衡”就是指工作在传输层上,基于 TCP/IP 协议的特性,例如 IP 地址、端口号等实现对后端服务器的负载均衡。
所谓的“七层负载均衡”就是指工作在应用层上,看到的是 HTTP 协议,解析 HTTP 报文里的 URI、主机名、资源类型等数据,再用适当的策略转发给后端服务器。

TCP/IP 协议栈的工作方式

TCP/IP 协议栈是如何工作的呢?
你可以把 HTTP 利用 TCP/IP 协议栈传输数据想象成一个发快递的过程。
假设你想把一件毛绒玩具送给朋友,但你要先拿个塑料袋套一下,这件玩具就相当于 HTTP 协议里要传输的内容,比如 HTML,然后 HTTP 协议为它加一个 HTTP 专用附加数据。
你把玩具交给快递小哥,为了保护货物,他又加了层包装再贴了个标签,相当于在 TCP 层给数据再次打包,加上了 TCP 头。
接着快递小哥下楼,把包裹放进了三轮车里,运到集散点,然后再装进更大的卡车里,相当于在 IP 层、MAC 层对 TCP 数据包加上了 IP 头、MAC 头。

之后经过漫长的运输,包裹到达目的地,要卸货再放进另一位快递员的三轮车,就是在 IP层、MAC 层传输后拆包。
快递员到了你朋友的家门口,撕掉标签,去除了 TCP 层的头,你朋友再拆掉塑料袋包装,也就是 HTTP 头,最后就拿到了玩具,也就是真正的 HTML 页面。
这个比喻里省略了很多 TCP/IP 协议里的细节,比如建连、路由、数据切分与重组、错误检查等,但核心的数据传输过程是差不多的。
HTTP 协议的传输过程就是这样通过协议栈逐层向下,每一层都添加本层的专有数据,层层打包,然后通过下层发送出去。
接收数据则是相反的操作,从下往上穿过协议栈,逐层拆包,每层去掉本层的专有头,上层就会拿到自己的数据。
但下层的传输过程对于上层是完全“透明”的,上层也不需要关心下层的具体实现细节,所以就 HTTP 层次来看,它不管下层是不是 TCP/IP 协议,看到的只是一个可靠的传输链路,只要把数据加上自己的头,对方就能原样收到。
在这里插入图片描述

小结

  1. TCP/IP 分为四层,核心是二层的 IP 和三层的 TCP,HTTP 在第四层;
  2. OSI 分为七层,基本对应 TCP/IP,TCP 在第四层,HTTP 在第七层;
  3. OSI 可以映射到 TCP/IP,但这期间一、五、六层消失了;
  4. 日常交流的时候我们通常使用 OSI 模型,用四层、七层等术语;
  5. HTTP 利用 TCP/IP 协议栈逐层打包再拆包,实现了数据传输,但下面的细节并不可见。

PS:本文是观看极客之后的笔记。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Probit模型是一种离散选择模型,常用于分析二元选择数据,比如一个人是否购买某个产品。Probit模型假设选择行为服从正态分布,通过最大似然估计来估计模型参数。以下是一个C++带类实现离散选择模型Probit模型的示例代码: ```cpp #include <iostream> #include <cmath> #include <vector> using namespace std; class ProbitModel { private: vector<double> X; // 自变量 vector<int> Y; // 因变量 int n; // 样本数 int k; // 自变量个数 double theta; // 参数 double LL; // 对数似然函数值 public: ProbitModel(vector<double> x, vector<int> y) { X = x; Y = y; n = x.size(); k = 1; } // 似然函数 double likelihood() { double sum = 0.0; for (int i = 0; i < n; i++) { double z = X[i] * theta; sum += Y[i] * log(CDF(z)) + (1 - Y[i]) * log(1 - CDF(z)); } return sum; } // 累积分布函数 double CDF(double z) { return 0.5 * (1 + erf(z / sqrt(2))); } // 一阶导数 double firstDerivative() { double sum = 0.0; for (int i = 0; i < n; i++) { double z = X[i] * theta; sum += (Y[i] - CDF(z)) * X[i] / CDF(z) / (1 - CDF(z)); } return sum; } // 二阶导数 double secondDerivative() { double sum = 0.0; for (int i = 0; i < n; i++) { double z = X[i] * theta; sum += -X[i] * X[i] * CDF(z) * (1 - CDF(z) + z * exp(-z * z / 2)) / pow(CDF(z), 2) / pow(1 - CDF(z), 2); } return sum; } // 牛顿法求解 void fit() { double epsilon = 1e-6; // 迭代终止条件 int maxIter = 1000; // 最大迭代次数 double delta; // 梯度 double deltaTheta; // 参数更新量 int iter = 0; // 迭代次数 while (iter < maxIter) { double f1 = firstDerivative(); double f2 = secondDerivative(); delta = -f1 / f2; deltaTheta = delta; theta += deltaTheta; LL = likelihood(); if (abs(deltaTheta) < epsilon) { break; } iter++; } } // 获取参数 double getTheta() { return theta; } // 获取对数似然函数值 double getLL() { return LL; } }; int main() { vector<double> X{1.0, 2.0, 3.0, 4.0, 5.0}; vector<int> Y{0, 0, 1, 1, 1}; ProbitModel pm(X, Y); pm.fit(); cout << "theta = " << pm.getTheta() << endl; cout << "LL = " << pm.getLL() << endl; return 0; } ``` 以上代码实现了一个简单的Probit模型,使用了牛顿法来求解模型参数。在main函数中,我们定义了一个样本,其中X为自变量,Y为因变量,表示是否购买某个产品。然后我们创建了一个ProbitModel对象pm,并调用其fit方法来拟合模型并求解参数。最后,我们输出了参数theta和对数似然函数值LL。 需要注意的是,Probit模型假设选择行为服从正态分布,因此我们在实现CDF函数时使用了误差函数erf,这需要包含cmath头文件。此外,由于Probit模型涉及到对数似然函数的计算,因此我们需要对结果进行判断,避免出现NaN或-inf等不合法的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值