当前位置: 首页 > article >正文

网络原理 TCP与UDP协议

 博主主页: 码农派大星.

    数据结构专栏:Java数据结构

 数据库专栏:MySQL数据库

JavaEE专栏:JavaEE

关注博主带你了解更多数据结构知识

1.应用层

之前编写完了基本的 java socket ,要知道,我们之前所写的所有代码都在应⽤层,都是为了 完成某项业务.

应用层是我们以后工作开发中经常用到的,主要涉及两种情况:

1.使用别人已经创建好的应用层协议(比如http)

2.自己定义应用层协议:

1)明确前后端交互过程中,需要传递哪些信息

2)明确组织这些信息的格式

针对信息组织方式有很多种(确保前端后端是同一种方式)

关于组织数据的格式:

1.xml

通过标签来组织数据

<request>
	<userID>10</userID>
	<position>E45I60</position>
</request>

优点:可读性提高
缺点:标签写起来非常繁琐,传输的时候消耗额外网络带宽

2.json 

当前使用非常主流的网络通信的数格式

通过键值对来组织数据

{
	"userID":"10",
	"position":"E40I60"
}

优点可读性较高,比xml简洁
缺点:传输的时候消耗额外网络带宽

3.yml(yaml)

强制要求了数据的格式

request:
   userld: 1001;
   position:"E60N45"

优点:可读性非常高,不额外消耗带宽

4.google protobuffer

前三个方案,都是关注可读性, protobuffer关注性能,牺牲了可读性(通过二进制的方式组织数据)

而protobuffer直接通过"位置"约定字段的含义,不需要传输key的名字,也会针对传输的数值,进行二进制的编码,起到一些"压缩"效果,极大缩短了传输的数据体积,带宽消耗就越小,效率越高.

2.传输层

传输层包含两个重要的协议UDP和TCP。
UDP:无连接,不可靠,面向数据报,全双工
TCP:有连接,可靠,面向字节流,全双工


端口号:占2个字节写一个服务器的时候必须手动指定一个端口号,用来区分不同程序。但写客户端的时候不用手动指定,系统会自动分配。同一时刻,同一个机器上,同一个协议,一个端口只能被一个进程绑定,一个进程可以绑定多个端口
1-1023称为知名端口号,给一些比较知名的服务器使用例如:22为ssh服务器,80为http协议,443为https服务器。1024-65535为普通端口号。

1.UDP协议

UDP报头:一共占8个字节,每一个部分都各占两个字节。

UDP报文长度:占2个字节,最长65535即64kb,这个长度是定长的,不能最初修改。 

校验和: 网络传输过程中,受到环境因素(电信号,电磁波,光信号)的影响,使里面的传输信号发生改变,校验和存在的目的就是为了"发现"或"纠正",这样的错误.

随着业务发展,UDP的64KB已经不够满足业务要求了 ,所以TCP就很好来解决,并且对长度就没有限制了,自身也有可靠传输机制,代码修改成本也比较低

2.TCP协议

TCP全称为"传输控制协议(Transmission Control Protocol"),要对数据的传输进⾏⼀个详细的控制

源/⽬的端⼝号:表⽰数据是从哪个进程来,到哪个进程去; 

32位序号/32位确认号:    后面介绍  ;

4位TCP报头⻓度:表⽰该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最⼤⻓度是15 * 4=60

保留(6)位: 充分吸取UDP报文长度无法扩展的教训,保留(6)位用来考虑未来的可扩展性,用来未来新增某个属性或者某个属性长度不够用,就可把保留位拿出来用.

6位标志位:

◦ URG:紧急指针是否有效

◦ ACK:确认号是否有效

◦ PSH:提⽰接收端应⽤程序⽴刻从TCP缓冲区把数据读⾛

◦ RST:对⽅要求重新建⽴连接;我们把携带RST标识的称为复位报⽂段

◦ SYN:请求建⽴连接;我们把携带SYN标识的称为同步报⽂段

◦ FIN:通知对⽅,本端要关闭了,我们称携带FIN标识的为结束报⽂段

2.1.确认应答

TCP的一个重要机制就是可靠传输,可靠传输就是当发送方把信息发出去,能够知道接收方是否接受了数据,一旦发现对方没有接受数据,那么发送方就会通多一定的手段来进行补救。

当发送方把信息发出去,接收方如收到信息,那么就会返回一个应答报文给发送方,如果发送方收到了这个报文,那么就证明信息发送成功了。但是在这个过程中可能会出现一些问题:例如我连续发送了两次请求,但是我后发送的消息却先响应了。 

为了避免出现这样的情况,TCP就需要确保应答报文和发出去的数据能够相互对应,即使出现后发先至的现象时,仍然能够按照正常的顺序来理解数据:我们发数据的时候就给数据编一个号,同时接收端做出响应也编一个号,这个时候就需要用到报头中的32位序号和32位确认序号。 

 --------------------------------------------------完美分割线------------------------------------------------------------

TCP将每个字节的数据都进⾏了编号.即为序列号 

每⼀个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下⼀次你从哪⾥开始发.

 

接收方这边调用read的时候如果没有数据,就会阻塞等待(前面代码写的是scanner读取, 本质上就是调用InputStream.read),此时虽然1001-2000这个数据到了,但是B不会让read解除阻塞,读到1001-2000这个数据还是要继续阻塞等待.直到说1-1000这个数据到达之后,read才会解除阻塞才会读取到1-1000,1001-2000,2001-3000数据,确保发送方write的顺序和接收方read的顺序是始终保持一致的

 B接收方这边,操作系统内核里,会有一段内存空间,作为"内存缓冲区",收到的数据,就会先在接收缓冲区排队等待,只到开头的数据到了,应用程序才能真正读取到里面的数据.

2.2 超时重传 


http://www.kler.cn/a/283284.html

相关文章:

  • React的基础API介绍(二)
  • NAT网络工作原理和NAT类型
  • 探索Pillow库:Python图像处理的瑞士军刀
  • 假期增设:福祉与负担并存,寻求生活经济平衡之道
  • 【初阶数据结构与算法】链表刷题之移除链表元素、反转链表、找中间节点、合并有序链表、链表的回文结构
  • 灰狼优化算法
  • 本地构建spotbugs,替换gradle的默认仓库地址。
  • chapter08-面向对象编程——(Object类详解)——day09
  • 【C++ Primer Plus习题】7.5
  • Docker方式部署K8s集群
  • 灵神算法题单——不定长滑动窗口(求最长最大)
  • C#入门(13)if语句
  • HTML简单了解和基础知识记录
  • 《机器学习》 基于GANs构建数字图像生成器 探索深度学习世界
  • 群晖(Docker Compose)配置 frp 服务
  • 移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——8.stackqueuepriority_queue(模拟实现)
  • zset使用lua实现取最高分数中的随机成员
  • 使用notepad++将shell脚本转为UNIX格式方法(主要差别在换行符)
  • MySQL中的锁详解
  • AndroidStudio无线连接Android手机进行调试
  • 利润暴涨507%的携程,做对了什么?
  • C++/Qt 多媒体(续三)
  • 酒店管理系统小程序(包含源码C++实现)
  • 生成和应用patch
  • Redis入门篇 - CentOS 7下载、安装Redis实操演示
  • 每天学习一个基础算法之顺序查找