之前我们提到了流式套接字和数据报式套接字,在介绍中,我们说到了流式套接字是面向连接的套接字,数据报套接字是面向无连接的套接字。那么面向连接的和面向无连接的套接字有什么区别呢?
举个例子简单地说明面向连接就像有一条管道连接着发送端和接收端,数据包都通过这条管道来传输。当然,两台计算机在通信之前必须先搭建好管道。
无连接就像无头苍蝇乱飞,数据包从发送端到接收端并没有固定的线路,想怎么走就怎么走,只要能到达就行。每个数据包都比较自私,不和别人分享自己的线路,但是,大家最终都能到达接收端。
为了大家能够更深入的理解,我将为大家用图示说明。
上图是一个简化互联网模型,H1 ~ H6 表示计算机,A~E 表示路由器,发送端发送的数据必须经过路由器的转发才能到达接收端。
假设 H1 要发送若干个数据包给 H6,那么有多条路径可以选择,比如:
路径①:H1 --> A --> C --> E --> H6
路径②:H1 --> A --> B --> E --> H
路径③:H1 --> A --> B --> D --> E --> H6
路径④:H1 --> A --> B --> C --> E --> H6
路径⑤:H1 --> A --> C --> B --> D --> E --> H6
面向连接的套接字在正式通信之前要先确定一条路径,没有特殊情况的话,以后就固定使用这条路径来传递数据包了。当然,路径被破坏的话,比如某个路由器断电了,那么会重新建立路径。
很多网络通信教程中,这条预先建立好的路径被称为“虚电路”,就是一条虚拟的通信电路。
为了保证数据包准确、顺序地到达,发送端在发送数据包以后,必须得到接收端的确认才能发送下一个数据包;如果数据包已经发出去了,在数据包发出去的一段时间后仍没有接收端的回应,那么发送端就会重新再发送一次,直到得到接收端的回应。这样就能保证,发送端发送的所有数据包都能准确有序地到达接收端,那么发送端如何得到接收端的回应呢?这就像两个小人在互相发消息的过程,发送端小人为每一个数据包分配ID,然后发送给接收端小人,接收端小人在接收到数据包后就会给发送端小人也回复一个数据包,并且回复发送端:我接收到了一个ID是XX的数据包,就导致了面向连接的套接字会比无连接的套接字多出很多数据包。
面向无连接的套接字,每个数据包都可以选择不同的路径,比如第一个数据包选择路径②,第二个数据包选择路径④,第三个数据包选择路径①……当然,它们也可以选择相同的路径,但那不过是拐一年摇一年的感觉,缘分呐。
每个数据包之间都是一个独立的个体,它们都有着我命由我不由天的气势,它们不服管啊,它们非要各走各路,谁也不care谁,但是它们除了迷路的和发生意外的最后都能到达 H6。可到达的顺序是不确定的,比如:
第一个数据包选择了一条比较长的路径(比如路径⑤),第三个数据包选择了一条比较短的路径(比如路径①),虽然第一个数据包很早就出发了,但是走的路比较远,最终还是晚于第三个数据包达到。
还有一些意外情况的发生,比如:
第一个数据包选择了路径①,但是路由器C突然断电了,那它就到不了 H6 了。第三个数据包选择了路径②,虽然路不远,但是太拥堵,以至于它等待的时间太长,路由器把它丢弃了。
总之,对于无连接的套接字,数据包在传输过程中会发生各种不测,也会发生各种奇迹。H1 只负责把数据包发出,至于它什么时候到达,先到达还是后到达,有没有成功到达,H1 都不管了;H6 也没有选择的权利,只能被动接收,收到什么算什么,爱用不用。
无连接套接字遵循的是尽最大努力完成任务的原则,做不到了也没办法。谁让无连接套接字提供的就是没有质量保证的服务呢。人家讲究的就是快而广比如广播。
本文固定URL:https://www.dotcpp.com/course/769
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程