TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,即收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来。
TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。
应用层 | 应用程序间沟通的层,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等(在TCP/IP的五层参考模型中,应⽤层对应OSI参考模型的哪⼏层?) |
传输层 | 提供了节点间的数据传送服务,如传输控制协议(TCP)、用户数据报协议(UDP)等,TCP和UDP给数据包加入传输数据并把它传输到下一层中,这一层负责传送数据,并且确定数据已被送达并接收。 |
互连网络层 | 负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否被正确接收),如网际协议(IP)。 |
网络接口层(数据链路层) | 对实际的网络媒体的管理,定义如何使用实际网络(如Ethernet、Serial Line等)来传送数据 |
OSI模型(OSI/RM,Open Systems Interconnection Reference Model,开放式通信系统互联参考模型),是国际标准化组织(ISO)提出的一个试图使各种计算机在世界范围内互连为网络的标准框架,简称OSI。
层名称 | 传输单位 | 作用 |
物理层 | 比特流 | 规定了激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性以及过程特性。该层为上层协议提供了一个传输数据的物理媒体。在这一层,数据的单位称为比特(bit)。属于物理层定义的典型规范代表包括:EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45等。设备之间比特流的传输,物理接口,电气特性等 |
数据链路层 | 帧 | 数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。在这一层,数据的单位称为帧(frame)。数据链路层协议的代表包括:SDLC、HDLC、PPP、STP、帧中继等。将上层数据封装成帧,用MAC地址访问媒介,错误检测与修正 |
网络层(Network Layer) | 包 | 负责对子网间的数据包进行路由选择。网络层还可以实现拥塞控制、网际互连等功能。在这一层,数据的单位称为数据包(packet)。网络层协议的代表包括:IP、IPX、RIP、OSPF等(路由选择协议位于网络层)。。提供逻辑地址(IP)、选路,数据从源端到目的端的传输 |
传输层(Transport Layer) | 段 | 第一个端到端,即主机到主机的层次。传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输。此外,传输层还要处理端到端的差错控制和流量控制问题。在这一层,数据的单位称为数据段(segment)。传输层协议的代表包括:TCP、UDP、SPX等。实现网络不同主机上用户进程之间的数据通信,可靠与不可靠的传输,传输层的错误检测,流量控制等 |
会话层 | 数据 | 管理主机之间的会话进程,即负责建立、管理、终止进程之间的会话。会话层还利用在数据中插入校验点来实现数据的同,提供包括访问验证和会话管理在内的建立和维护应用之间通信的机制,如服务器验证用户登录便是由会话层完成的 |
表示层(Presentation Layer) | 对上层数据或信息进行变换以保证一个主机应用层信息可以被另一个主机的应用程序理解。表示层的数据转换包括数据的加密、压缩、格式转换等,主要解决用户信息的语法表示问题,如加密解密 | |
应用层(Application LAyer) | 为操作系统或网络应用程序提供访问网络服务的接口,确定进程之间通信的性质以满足用户需要以及提供网络与用户应用 |
OSI模型是一个参考标准,解释协议相互之间应该如何相互作用。TCP/IP协议是美国国防部发明的,是让互联网成为了目前这个样子的标准之一。 OSI模型中没有清楚地描绘TCP/IP协议,但是在解释TCP/IP协议时很容易想到OSI模型。两者的主要区别如下:
TCP/IP协议中的应用层处理OSI模型中的会话层、表示层和应用层的功能。
TCP/IP协议中的传输层并不能总是保证在传输层可靠地传输数据包,而OSI模型可以做到。TCP/IP协议还提供一项名为UDP(用户数据报协议)的选择。UDP不能保证可靠的数据包传输。
将MAC地址08:00:20:0A:8C:6D解析为IP地址192.168.0.1
如图,ARP协议是把查询IP地址对应的MAC地址,而RARP是查询MAC地址对应的IP地址:
TCP/IP协议中,传输层包括TCP和UDP,TCP和UDP都提供了面向连接的数据传输服务,其中,TCP提供的是不可靠的数据传输服务。
在unix服务器http://www.openlab.com.cn上提供了基于TCP的时间服务应用,该应用使用port为13。创建连接到此服务器的语句是:Socket s = new Socket(“www.openlab.com.cn”, 13);
1.建立socket;2. 获得I/O流;3. 对I/O流进行读写操作;4. 关闭I/O流;5. 关闭socket
1.创建一个服务器socket;2. 从服务器socket接受客户连接请求;3.创建一个服务线程处理新的连接;4. 在服务线程中,从socket中获得I/O流;5.对I/O流进行读写操作,完成与客户的交互;6.关闭I/O流;7.关闭socket
TCP报头
TCP选项有哪些
TCP首部选项字段多达40B,一些常用的字段有:
1)选项结束字段(EOP,0x00),占1B,一个报文段仅用一次。放在末尾用于填充,用途是说明:首部已经没有更多的消息,应用数据在下一个32位字开始处
2)无操作字段(NOP, 0x01),占1B,也用于填充,放在选项的开头
3)MSS(最大报文段长度),格式如下:种类(1B,值为2),长度(1B,值为4),数值(2B)
用于在连接开始时确定MSS的大小,如果没有确定,就用默认的(一般实现是536B)
4)窗口扩大因子,格式如下:种类(1B,值为3),长度(1B,值为3),数值(1B)
新窗口值 = 首部窗口值 * 2的(扩大因子)次方
当通信双方认为首部的窗口值还不够大的时候,在连接开始时用这个来定义更大的窗口。仅在连接开始时有效。一经定义,通信过程中无法更改。
5)时间戳(应用测试RTT和防止序号绕回)
6)允许SACK和SACK选项
两个主机通过三次通信可以建立TCP连接,使用完后,进行四次通信断开连接。我们通常形象地把它们叫做三次握手和四次挥手。
客户端:我要和你建立连接
服务端:你真的要和我建立连接么?
客户端:我真的要和你建立连接,成功。
为了防止已失效的连接请求报文突然又传送到了服务端,因而产生错误。客户端发出的连接请求报文并未丢失,而是在某个网络节点长时间滞留了,以致延误到链接释放以后的某个时间才到达 Server 。
1. SYN洪泛攻击
服务器处于SYN_Wait的状态:
1)伪装的IP向服务器发送一个SYN请求建立连接,然后服务器向该IP回复SYN和ACK,但是找不到该IP对应的主机,当超时时服务器收不到ACK会重复发送。当大量的攻击者请求建立连接时,服务器就会存在大量未完成三次握手的连接,服务器主机backlog被耗尽而不能响应其它连接。即SYN泛洪攻击 (属于DOS的一种,发送大量的半连接请求,耗费CPU和内存资源,引起网络堵塞甚至系统瘫痪)
当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击
netstat -n -p TCP | grep SYN_RECV
防范措施:
1、降低SYN timeout时间,使得主机尽快释放半连接的占用
2、采用SYN cookie设置,如果短时间内连续收到某个IP的重复SYN请求,则认为受到了该IP的攻击,丢弃来自该IP的后续请求报文
3、在网关处设置过滤,拒绝将一个源IP地址不属于其来源子网的包进行更远的路由
2)当一个主机向服务器发送SYN请求连接,服务器回复ACK和SYN后,攻击者截获ACK和SYN。然后伪装成原始主机继续与服务器进行通信。
2. DOS攻击(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)
DOS攻击利用合理的服务请求占用过多的服务资源,使正常用户的请求无法得到相应。
常见的DOS攻击有计算机网络带宽攻击和连通性攻击。
带宽攻击指以极大的通信量冲击网络,使得所有可用网络资源都被消耗殆尽,最后导致合法的用户请求无法通过。
连通性攻击指用大量的连接请求冲击计算机,使得所有可用的操作系统资源都被消耗殆尽,最终计算机无法再处理合法用户的请求。
3. 死亡值ping
许多操作系统的TCP/IP协议栈规定ICMP包大小为64KB(网间控制报文),且在对包的标题头进行读取之后,要根据该标题头里包含的信息来为有效载荷生成缓冲区。
”死亡值ping”就是故意产生畸形的测试ping包,声称自己的尺寸超过ICMP上限,也就是加载的尺寸超过64KB上限,使未采取保护措施的网络系统出现内存分配错误,导致TCP/IP协议栈崩溃,最终接收方宕机。
客户端:我要和你断开连接
服务端:好的,断吧。
服务端:我也要和你断开连接
客户端:好的,断吧。
1. 可靠终止TCP连接。如果最后一个ACK报文因为网络原因被丢弃,此时server因为没有收到ACK而超时重传FIN报文,处于TIME_WAIT状态的client可以继续对FIN报文做回复,向server发送ACK报文。
2. 保证让迟来的TCP报文段有足够的时间被识别和丢弃。连接结束了,网络中的延迟报文也应该被丢弃掉,以免影响立刻建立的新连接。
链接:
假设 Client 向 Server 连续发送了两个数据包,用 packet1 和 packet2 来表示,那么服务端收到的数据可以分为三种情况:
1. 接收端正常收到两个数据包,没有发生拆包和粘包的现象。
2. 接收端只收到一个数据包,但是这一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包。这种情况由于接收端不知道这两个数据包的界限,所以对于接收端来说很难处理。
3. 这种情况有两种表现形式,接收端收到了两个数据包,但是这两个数据包要么是不完整的,要么就是多出来一块,这种情况即发生了拆包和粘包。这两种情况如果不加特殊处理,对于接收端同样是不好处理的。
1. 要发送的数据大于TCP 发送缓冲区剩余空间大小,将会发生拆包。
2. 待发送数据大于 MSS(最大报文长度),TCP 在传输前将进行拆包。
3. 要发送的数据小于 TCP 发送缓冲区的大小,TCP 将多次写入缓冲区的数据一次发送出去,将会发生粘包。
4. 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。
UDP 是基于报文发送的,UDP首部采用了 16bit 来指示 UDP 数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。
而 TCP 是基于字节流的,虽然应用层和 TCP 传输层之间的数据交互是大小不等的数据块,但是 TCP 并没有把这些数据块区分边界,仅仅是一连串没有结构的字节流;另外从 TCP 的帧结构也可以看出,在 TCP 的首部没有表示数据长度的字段,基于上面两点,在使用 TCP 传输数据时,才有粘包或者拆包现象发生的可能。
由于TCP本身是面向字节流的,无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,归纳如下:
消息定长:发送端将每个数据包封装为固定长度(不够的可以填充0),这样接收端每次接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
设置消息边界:服务端从网络流中按消息边界分离出消息内容。在包尾增加回车换行符进行分割,例如FTP协议。
将消息分为消息头和消息体:消息头中包含表示消息总长度(或者消息体长度)的字段。
更复杂的应用层协议比如 Netty 中实现的一些协议都对粘包、拆包做了很好的处理。
窗口是缓存的一部分,用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。
发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。
接收窗口只会对窗口内最后一个按序到达的字节进行确认,例如接收窗口已经收到的字节为 {31, 34, 35},其中 {31} 按序到达,而 {34, 35} 就不是,因此只对字节 31 进行确认。发送方得到一个字节的确认之后,就知道这个字节之前的所有字节都已经被接收。
流量控制是为了控制发送方发送速率,保证接收方来得及接收。接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。实际上,为了避免此问题的产生,发送端主机会时不时的发送一个叫做窗口探测的数据段,此数据段仅包含一个字节来获取最新的窗口大小信息。