我把自己以往的文章汇总成为了 Github ,欢迎各位大佬 star
https://github.com/crisxuan/bestJavaer
已提交此篇文章
位于应用层和 络层之间,是 OSI 分层体系中的第四层,同时也是 络体系结构的重要部分。运输层主要负责 络上的端到端通信。
TCP 如何判断是哪个端口的呢p>
还记得数据包的结构吗,这里来回顾一下
但是为了统一,一般在计算机 络中我们统一称 TCP 和 UDP 的 文为 ,这个就相当于是约定,到底如何称呼不用过多纠结啦。
套接字
在 TCP 或者 UDP 发送具体的 文信息前,需要先经过一扇 ,这个门就是,套接字向上连接着应用层,向下连接着 络层。在操作系统中,操作系统分别为应用和硬件提供了。而在计算机 络中,套接字同样是一种接口,它也是有接口 API 的。
使用 TCP 或 UDP 通信时,会广泛用到套接字的 API,使用这套 API 设置 IP 地址、端口 ,实现数据的发送和接收。
- socket 中的 API 用于创建通信链路中的端点,创建完成后,会返回描述该套接字的。
就像使用文件描述符来访问文件一样,套接字描述符用来访问套接字。
- 当应用程序具有套接字描述符后,它可以将唯一的名称绑定在套接字上,服务器必须绑定一个名称才能在 络中访问
- 在为服务端分配了 socket 并且将名称使用 bind 绑定到套接字上后,将会调用 listen api。 表示客户端愿意等待连接的意愿,listen 必须在 accept api 之前调用。
- 客户端应用程序在流套接字(基于 TCP)上调用 发起与服务器的连接请求。
- 服务器应用程序使用API 接受客户端连接请求,服务器必须先成功调用 bind 和 listen 后,再调用 accept api。
- 在流套接字之间建立连接后,客户端和服务器就可以发起 read/write api 调用了。
- 当服务器或客户端要停止操作时,就会调用 API 释放套接字获取的所有系统资源。
虽然套接字 API 位于应用程序层和传输层之间的通信模型中,但是套接字 API 不属于通信模型。套接字 API 允许应用程序与传输层和 络层进行交互。
在往下继续聊之前,我们先播放一个小插曲,简单聊一聊 IP。
聊聊 IP
是的缩写,是 TCP/IP 体系中的协议。设计 IP 的初衷主要想解决两类问题
- 提高 络扩展性:实现大规模 络互联
- 对应用层和链路层进行解藕,让二者独立发展。
IP 是整个 TCP/IP 协议族的核心,也是构成互联 的基础。为了实现大规模 络的互通互联,IP 更加注重适应性、简洁性和可操作性,并在可靠性做了一定的牺牲。IP 不保证分组的交付时限和可靠性,所传送分组有可能出现丢失、重复、延迟或乱序等问题。
我们知道,TCP 协议的下一层就是 IP 协议层,既然 IP 不可靠,那么如何保证数据能够准确无误地到达呢p>
这就涉及到 TCP 传输机制的问题了,我们后面聊到 TCP 的时候再说。
端口
在聊端口 前,先来聊一聊文件描述以及 socket 和端口 的关系
为了方便资源的使用,提高机器的性能、利用率和稳定性等等原因,我们的计算机都有一层软件叫做操作系统,它用于帮我们管理计算机可以使用的资源,当我们的程序要使用一个资源的时候,可以向操作系统申请,再由操作系统为我们的程序分配和管理资源。通常当我们要访问一个内核设备或文件时,程序可以调用系统函数,系统就会为我们打开设备或文件,然后返回一个文件描述符fd(或称为ID,是一个整数),我们要访问该设备或文件,只能通过该文件描述符。可以认为该编 对应着打开的文件或设备。
而当我们的程序要使用 络时,要使用到对应的操作系统内核的操作和 卡设备,所以我们可以向操作系统申请,然后系统会为我们创建一个套接字 Socket,并返回这个 Socket 的ID,以后我们的程序要使用 络资源,只要向这个 Socket 的编 ID 操作即可。而我们的每一个 络通信的进程至少对应着一个 Socket。向 Socket 的 ID 中写数据,相当于向 络发送数据,向 Socket 中读数据,相当于接收数据。而且这些套接字都有唯一标识符——文件描述符 fd。
端口 是 位的非负整数,它的范围是 0 – 65535 之间,这个范围会分为三种不同的端口 段,由 Internet 码分配机构 IANA 进行分配
- 周知/标准端口 ,它的范围是 0 – 1023
- 注册端口 ,范围是 1024 – 49151
- 私有端口 ,范围是 49152 – 6553
一台计算机上可以运行多个应用程序,当一个 文段到达主机后,应该传输给哪个应用程序呢么知道这个 文段就是传递给 HTTP 服务器而不是 SSH 服务器的呢p>
是凭借端口 吗文到达服务器时,是端口 来区分不同应用程序的,所以应该借助端口 来区分。
举个例子反驳一下 cxuan,假如到达服务器的两条数据都是由 80 端口发出的你该如何区分呢说到达服务器的两条数据端口一样,协议不同,该如何区分呢p>
所以仅凭端口 来确定某一条 文显然是不够的。
互联 上一般使用 源 IP 地址、目标 IP 地址、源端口 、目标端口 来进行区分。如果其中的某一项不同,就被认为是不同的 文段。这些也是 的基础。
确定端口
在实际通信之前,需要先确定一下端口 ,确定端口 的方法分为两种:
- 标准既定的端口
标准既定的端口 是静态分配的,每个程序都会有自己的端口 ,每个端口 都有不同的用途。端口 是一个 16 比特的数,其大小在 0 – 65535 之间,0 – 1023 范围内的端口 都是动态分配的既定端口 ,例如 HTTP 使用 80 端口来标识,FTP 使用 21 端口来标识,SSH 使用 22 来标识。这类端口 有一个特殊的名字,叫做 。
- 时序分配的端口
第二种分配端口 的方式是一种动态分配法,在这种方法下,客户端应用程序可以完全不用自己设置端口 ,凭借操作系统进行分配,操作系统可以为每个应用程序分配互不冲突的端口 。这种动态分配端口 的机制即使是同一个客户端发起的 TCP 连接,也能识别不同的连接。
多路复用和多路分解
我们上面聊到了在主机上的每个套接字都会分配一个端口 ,当 文段到达主机时,运输层会检查 文段中的目的端口 ,并将其定向到相应的套接字,然后 文段中的数据通过套接字进入其所连接的进程。下面我们来聊一下什么是多路复用和多路分解的概念。
多路复用和多路分解分为两种,即的多路复用(多路分解)和的多路复用(多路分解)
无连接的多路复用和多路分解
开发人员会编写代码确定端口 是周知端口 还是时序分配的端口 。假如主机 A 中的一个 10637 端口要向主机 B 中的 45438 端口发送数据,运输层采用的是 协议,数据在应用层产生后,会在运输层中加工处理,然后在 络层将数据封装得到 IP 数据 ,IP 数据包通过链路层尽力而为的交付给主机 B,然后主机 B 会检查 文段中的端口 判断是哪个套接字的,这一系列的过程如下所示
面向连接的多路复用与多路分解
如果说无连接的多路复用和多路分解指的是 UDP 的话,那么面向连接的多路复用与多路分解指的是 TCP 了,TCP 和 UDP 在 文结构上的差别是,UDP 是一个二元组而 TCP 是一个四元组,即源 IP 地址、目标 IP 地址、源端口 、目标端口 ,这个我们上面也提到了。当一个 TCP 文段从 络到达一台主机时,这个主机会根据这四个值拆解到对应的套接字上。
- :这个字段占据 UDP 文头的前 16 位,通常包含发送数据 的应用程序所使用的 UDP 端口。接收端的应用程序利用这个字段的值作为发送响应的目的地址。这个字段是可选项,有时不会设置源端口 。没有源端口 就默认为 0 ,通常用于不需要返回消息的通信中。
- : 表示接收端端口,字段长为 16 位
- : 该字段占据 16 位,表示 UDP 数据 长度,包含 UDP 文头和 UDP 数据长度。因为 UDP 文头长度是 8 个字节,所以这个值最小为 8,最大长度为 65535 字节。
- :UDP 使用校验和来保证数据安全性,UDP 的校验和也提供了差错检测功能,差错检测用于校验 文段从源到目标主机的过程中,数据的完整性是否发生了改变。发送方的 UDP 对 文段中的 16 比特字的和进行反码运算,求和时遇到的位溢出都会被忽略,比如下面这个例子,三个 16 比特的数字进行相加
? 然后再将上面的结果和第三个 16 比特的数进行相加
文章知识点与官方知识档案匹配,可进一步学习相关知识 络技能树首页概览22961 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!