面向连接和无连接的套接字到底有什么区别?
上一节《套接字有哪些类型》提到,流格式套接字(Stream Sockets)就是“面向连接的套接字”,它基于 TCP 协议;数据报格式套接字(Datagram Sockets)就是“无连接的套接字”,它基于 UDP 协议。
这给大家造成一种印象,面向连接就是可靠的通信,无连接就是不可靠的通信,实际情况是这样吗?
另外,不管是哪种数据传输方式,都得通过整个 Internet 网络的物理线路将数据传输过去,从这个层面理解,所有的 socket 都是有物理连接的呀,为什么还有无连接的 socket 呢?
本节就来给大家解开种种谜团,加深大家对数据传输方式的认识。
从字面上理解,面向连接好像有一条管道,它连接发送端和接收端,数据包都通过这条管道来传输。当然,两台计算机在通信之前必须先搭建好管道。
无连接好像没头苍蝇乱撞,数据包从发送端到接收端并没有固定的线路,爱怎么走就怎么走,只要能到达就行。每个数据包都比较自私,不和别人分享自己的线路,但是,大家最终都能殊途同归,到达接收端。
这样理解没错,但是我相信这还不够深入,大家还是感觉云里雾里,没有看到本质。好,接下来就是见证奇迹的时刻,我会用实例给大家演示!
上图是一个简化的互联网模型,H1 ~ H6 表示计算机,A~E 表示路由器,发送端发送的数据必须经过路由器的转发才能到达接收端。
假设 H1 要发送若干个数据包给 H6,那么有多条路径可以选择,比如:
- 路径①:H1 --> A --> C --> E --> H6
- 路径②:H1 --> A --> B --> E --> H6
- 路径③:H1 --> A --> B --> D --> E --> H6
- 路径④:H1 --> A --> B --> C --> E --> H6
- 路径⑤:H1 --> A --> C --> B --> D --> E --> H6
数据包的传输路径是路由器根据算法来计算出来的,算法会考虑很多因素,比如网络的拥堵状况、下一个路由器是否忙碌等。
无连接的套接字
对于无连接的套接字,每个数据包可以选择不同的路径,比如第一个数据包选择路径④,第二个数据包选择路径①,第三个数据包选择路径②……当然,它们也可以选择相同的路径,那也只不过是巧合而已。
每个数据包之间都是独立的,各走各的路,谁也不影响谁,除了迷路的或者发生意外的数据包,最后都能到达 H6。但是,到达的顺序是不确定的,比如:
- 第一个数据包选择了一条比较长的路径(比如路径⑤),第三个数据包选择了一条比较短的路径(比如路径①),虽然第一个数据包很早就出发了,但是走的路比较远,最终还是晚于第三个数据包达到。
- 第一个数据包选择了一条比较短的路径(比如路径①),第三个数据包选择了一条比较长的路径(比如路径⑤),按理说第一个数据包应该先到达,但是非常不幸,第一个数据包走的路比较拥堵,这条路上的数据量非常大,路由器处理得很慢,所以它还是晚于第三个数据包达到了。
还有一些意外情况会发生,比如:
- 第一个数据包选择了路径①,但是路由器C突然断电了,那它就到不了 H6 了。
- 第三个数据包选择了路径②,虽然路不远,但是太拥堵,以至于它等待的时间太长,路由器把它丢弃了。
总之,对于无连接的套接字,数据包在传输过程中会发生各种不测,也会发生各种奇迹。H1 只负责把数据包发出,至于它什么时候到达,先到达还是后到达,有没有成功到达,H1 都不管了;H6 也没有选择的权利,只能被动接收,收到什么算什么,爱用不用。
无连接套接字遵循的是「尽最大努力交付」的原则,就是尽力而为,实在做不到了也没办法。无连接套接字提供的没有质量保证的服务。
面向连接的套接字
面向连接的套接字在正式通信之前要先确定一条路径,没有特殊情况的话,以后就固定地使用这条路径来传递数据包了。当然,路径被破坏的话,比如某个路由器断电了,那么会重新建立路径。
这条路径是由路由器维护的,路径上的所有路由器都要存储该路径的信息(实际上只需要存储上游和下游的两个路由器的位置就行),所以路由器是有开销的。
H1 和 H6 通信完毕后,要断开连接,销毁路径,这个时候路由器也会把之前存储的路径信息擦除。
在很多网络通信教程中,这条预先建立好的路径被称为“虚电路”,就是一条虚拟的通信电路。
为了保证数据包准确、顺序地到达,发送端在发送数据包以后,必须得到接收端的确认才发送下一个数据包;如果数据包发出去了,一段时间以后仍然没有得到接收端的回应,那么发送端会重新再发送一次,直到得到接收端的回应。这样一来,发送端发送的所有数据包都能到达接收端,并且是按照顺序到达的。
发送端发送一个数据包,如何得到接收端的确认呢?很简单,为每一个数据包分配一个 ID,接收端接收到数据包以后,再给发送端返回一个数据包,告诉发送端我接收到了 ID 为 xxx 的数据包。
面向连接的套接字会比无连接的套接字多出很多数据包,因为发送端每发送一个数据包,接收端就会返回一个数据包。此外,建立连接和断开连接的过程也会传递很多数据包。
不但是数量多了,每个数据包也变大了:除了源端口和目的端口,面向连接的套接字还包括序号、确认信号、数据偏移、控制标志(通常说的 URG、ACK、PSH、RST、SYN、FIN)、窗口、校验和、紧急指针、选项等信息;而无连接的套接字则只包含长度和校验和信息。
有连接的数据包比无连接大很多,这意味着更大的负载和更大的带宽。许多即时聊天软件采用 UDP 协议(无连接套接字),与此有莫大的关系。
总结
两种套接字各有优缺点:
- 无连接套接字传输效率高,但是不可靠,有丢失数据包、捣乱数据的风险;
- 有连接套接字非常可靠,万无一失,但是传输效率低,耗费资源多。
两种套接字的特点决定了它们的应用场景,有些服务对可靠性要求比较高,必须数据包能够完整无误地送达,那就得选择有连接的套接字(TCP 服务),比如 HTTP、FTP 等;而另一些服务,并不需要那么高的可靠性,效率和实时才是它们所关心的,那就可以选择无连接的套接字(UDP 服务),比如 DNS、即时聊天工具等。
面向连接和无连接的套接字到底有什么区别?相关推荐
- 深入理解Socket套接字原理
Socket套接字原理 1.什么是Socket 在计算机领域,套接字Socket作为计算机之间进行通信的固定的约定方式之一存在.这种太抽象了,我举个例子,我们要是用笔记本电脑前需要先对电脑供电,那供电 ...
- Linux网络编程 - 套接字与协议族
一 理解网络编程和套接字(socket) 1.1 网络编程和套接字概要 网络编程就是编程程序使两台连网的计算机可以互相交换数据.那么,这两台计算机之间用什么传输数据呢?首先需要物理连接.如今大部分计算 ...
- 嵌入式linux网络编程之——5年程序员给你深度讲解socket套接字
以下内容转载自 https://www.toutiao.com/i6827837032622981636/ 本文主要给大家分享网络七层概念之网络编程socket,前边的章节已经给大家讲述了链路层.物理 ...
- Linux网络编程之Socket套接字
一.Socket到底是什么 socket 这个英文单词的原意是"插口""插槽", 在网络编程中,它的意思是可以通过插口接入的方式,快速完成网络连接和数据收发.你 ...
- 《UNIX环境编程》第十六章--网络IPC:套接字
Contents 套接字接口 套接字描述符 寻址 字节序 地址格式 地址查询 绑定地址 建立连接 数据传输 套接字选项 带外数据 UNIX域套接字 使用套接字的示例 面向连接的ruptime 无连接的 ...
- Linux套接字聊天
Linux套接字 套接字是一种通信机制,凭借这种机制,客户/服务器系统的开发工作既可以在本地单机上进行,也可以跨网络进行. 套接字的特性有三个属性确定,它们是:域(domain),类型(type),和 ...
- C语言socket()函数解析(创建套接字)af地址族,ip地址类型(Address Family)INET(Inetnet)PF(Protocol Family)
文章目录 Linux 下的 socket() 函数 1) af 为地址族(Address Family),也就是 IP 地址类型 2) type 为数据传输方式/套接字类型 3) protocol 表 ...
- socket()函数用法详解:创建套接字
不管是 Windows 还是 Linux,都使用 socket() 函数来创建套接字.socket() 在两个平台下的参数是相同的,不同的是返回值. 在<socket是什么>一节中我们讲到 ...
- 套接字有哪些类型?socket有哪些类型?
这个世界上有很多种套接字(socket),比如 DARPA Internet 地址(Internet 套接字).本地节点的路径名(Unix套接字).CCITT X.25地址(X.25 套接字)等.但本 ...
最新文章
- Ubuntu 16.04.1 LTS上安装电源管理系统TLP
- Android:AS与Unity3D之间打包的各种坑及解决方案
- mysql 分时统计_mysql中数据统计的技巧备忘录
- 腾讯官方游戏《陆战之王 3D坦克大战》
- MySQL对于有大量重复数据表的处理方法
- 面试经验:求职面试时的835守则
- 4-2 父子组件的数据传递
- python复制文件到指定文件夹_python 拷贝文件夹下所有的文件到指定文件夹(不包括目录)...
- GPRS联网模块:广和通FIBOCOM_G510 支持接入机智云
- JZOJ 1667【AHOI2009】中国象棋——dp
- Font Awesome图标字体
- Keras验证集切分
- Ubuntu 安装 bashtop 资源监视器
- Uniapp设置页面的背景图片
- ASC18世界大学生超算竞赛题目分析以及思路总结
- Centos6.8系统镜像下载
- Linux2 6--中断机制中的 ksoftirqd
- Android 自定义View实现圆形头像(适用于任意布局)
- PaddleOCR学习(一)PaddleOCR安装与测试
- DB2存储过程入门实例
热门文章
- Java入参关键字_Java基础17-成员变量、return关键字和多参方法
- 国王放米粒的C语言程序,云南大学软件学院C语言实验米粒问题.doc
- 20211108 det(AB)=det(A)det(B)
- Linux下运行Jmeter脚本
- 数据仓库--基本概念
- Java面试集合(二)
- k-Means算法(Machine Learning in Action)基于python3.6
- D3引擎用正则运算的方式,实现智能设备APP消息推送
- safehandle 和析构函数
- Error: rpmdb open failed