为什么说一个tcp连接是会话层session的通道,不是通过socket来连接的吗?

admin 2025年6月19日20:47:18评论11 views字数 2468阅读8分13秒阅读模式

基础层:物理层(Physical)、数据链路层(Datalink)、网络层(Network)。

传输层(Transport)TCP-UDP协议层、Socket。

高级层:会话层(Session)、表示层(Presentation)、应用层(Application)。

为什么说一个tcp连接是会话层session的通道,不是通过socket来连接的吗?

计算机编程,如果不调用任何API函数,可能什么都做不了。

如果不相信,请你写段程序告诉我们

1 + 1 =

几乎每个可以工作的程序,都是在使用现有的API在工作,比如:

#include <stdio.h>

int main() {

printf("1+1=2n");

return 0;

}

通过加亮的printf函数,可以将结果打印在屏幕上,或者其它函数打印到文件里。

调用已有的API接口函数来编程,这是业界的共识,这样可以大大提高生产效率。

一位超级牛人,是否可以不调用任何接口函数,将1+1=2 这个结果打印到屏幕上来?

可以的,需要花费很多很多力气来编程,最终确实可以成功,但是生产效率特别低下。

如果将字符打印到屏幕这段最原始的代码封装成printf(),分享出来,别人直接就call一下,是不是就太简单了?

计算机太复杂了,编程亦然。TCP/IP为了让千千万万程序员日子好过一点,分享了两件秘密武器

秘密武器之一:关系集/仓库

不仅拥有收packet的仓库,还有发packet的仓库区,更维护着千丝万缕的关系网。它的名字其实准确应该叫“关系网大全”。西方计算机科学家对关系网理解显然没有东方民族深刻,故给它起一个非常抽象的名字,Socket

为什么说一个tcp连接是会话层session的通道,不是通过socket来连接的吗?

当你使用socket()这个接口成功申请仓库,你会得到这个仓库的编号,比如007。记住了,007号仓库就是你与这个世界(Internet)通信的关系网入口。

如果你用UDP申请的007仓库,你可以直接sendto(),发送你已经打包好的packet了,在sendto()里要记住带上仓库的编号007。你的packet就发出去了,甚至都没有在仓库里呆上0.1毫秒。简单吧?

这个sendto() 就是

秘密武器之二:操作集(Operations

TCP/IP会根据007编号,找到对应的关系网,并将目的IP、目的端口临时记在这个关系网里。凭借这个关系网,可以完成流水线的call chain,最终packet从网卡流出。

当返程的packet到来时,TCP/IP依赖于这个packet的五元组

UDP + Source IP + Destination IP + Source Port + Destination Port

计算一个hash,然后用这个hashhash表查询,得到仓库编号=007,于是就将packet放入007号仓库接收区。

内部关系网还维系着007号仓库关联的进程ID,于是唤醒对应的进程ID,进程的read()由于进程的唤醒而退出阻塞状态,从而将007号仓库的packet读出。

上文的sendto()read()都是操作集的成员。

但是,如果用户你申请的仓库不是UDP,而是TCP型号的仓库。通过socket()申请成功后,你不能立马用sendto()来发送packet

如果你执意要那么做,对不起,会出错的,系统不会睬你。

假如你成功申请到了008号仓库,接下来的所有操作都要带上008号仓库的编号,因为操作集的所有操作都需要008号关系网来维系

需要先用connect()本地的关系网,与接收端的关系网,逻辑上勾连起来,就是耳熟能详的建立TCP连接。

如果connect()成功返回,接下来你就可以用008号仓库来收发packet了。

上文的007号仓库,你可以将货物packet发到世界各地(Any,没有任何限制。

但是008号仓库,你只能发给一个目的地,即你用connect()连接的服务器的IP,记住了,这个IP地址是唯一的,(Only one)。

007号仓库发出的packet,只是名义上的,因为packet从来没有进入过007号仓库,而是直接从用户进程直接离开进入UDP/IP/NIC

008号仓库发出的packet,必须要进入008号仓库的发送缓冲区,然后由TCP来决定是否发送,何时发送,发送多少。

在发送的时刻,还会启动重传定时器,如果定时器响了,对方的ACK还没有到来。TCP会从008仓库将packet取出再次发送。

如果运气好,收到对方的ACK,由TCPpacket从发送区移走,并释放其占用的内存资源。

如果运气非常不好,网络断了,重传次数到达上限,TCPReset这个TCP连接。

Reset的潜台词是,将008好仓库维系的关系网全部释放。并发出Reset报文。如果对方收到Reset报文,无条件释放对应的关系网。

如果网络一直断着,接收方压根无法收到Reset报文,那么它就一直以为这个TCP连接依然健在。直到下次发送packet,才会触发对端的再次Reset

008号仓库所有的packet都发送完毕,还需要断开这个TCP连接,可以使用shutdown()close()来完成。

一旦双方都close(),先发出FIN报文的一方需要逗留time_wait,确保TCP连接这个逻辑通道上所有的packet都排尽了,才最终释放仓库。

由于008仓库是客户端,一般都是主动发出FIN报文的,故需要逗留time_wait,才能释放008号仓库所维系的关系网。

而服务器在自己的FIN报文被ACK之后,可以直接释放自己的关系网,将内存资源完全释放。

回顾一下

通过上文的描述,TCP连接是由用户通过connect()操作完成的。

但是,用户必须先用socket()成功申请到TCP型号的仓库。然后拿着申请到的008号仓库(关系集)去做connect()send()recv()操作集。

Socket关系集。没有它寸步难行。

socket()connect()send()recv()close()操作集。没有它们,什么也干不了。

原文始发于微信公众号(车小胖谈网络):为什么说一个tcp连接是会话层session的通道,不是通过socket来连接的吗?

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月19日20:47:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   为什么说一个tcp连接是会话层session的通道,不是通过socket来连接的吗?http://cn-sec.com/archives/4181962.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息