UDP 与 TCP

UDP 与 TCP

套接字(socket):ip+端口作为连接的端点,这种端点就叫做套接字,套接字就相当于从网络向进程或者从进程像网络传输数据的门户。所以主机和主机之间通信并不是直接将数据交给进程的,而是将数据交给一个中间的套接字,同时一个进程有一个或者多个套接字,而每个套接字都有唯一的标识符,标识符的格式取决于他是UDP还是TCP套接字。

UDP

UDP是无连接的传输协议,在使用UDP时发送方和接受方是没有握手的,只做了传输协议能做的最少的事情,除了复用/分解功能及少量 的差错检测外,几乎没有对IP增加别的东西,这就意味着当你选择UDP开发应用进程时差不多就是在直接与IP打交道。
UPD从进程得到数据,附加上多路复用的源和目标端口号字段,以及其他两个小的其他字段形成报文段交给网络层。网络层将该运输报文段封装到一个IP数据包中,传输到目标主机,当报文到达目标主机,UPD使用目的端口号将报文中的数据交给正确的应用进程。

报文段结构

image.png

TCP

TCP是面向连接的传输协议,两个进程发送数据前必须先相互发送某些预备报文段,以建立确保数据传输的参数,作为连接的一部分,连接的双方都要初始化许多与TCP连接相关的TCP状态参数。因此TCP只能在端系统中运行,因为连接状态必须完全保存在两个端系统中,中间的网络元素不会维持TCP连接状态,中间的元素如路由器,交换机等看到的只是数据报而不是连接。
TCP是全双工服务,即数据A-->流向B,则也能B--->A,即TCP是双向点对点的。

报文段结构

fd90ae8a61e577178b54ed7048783468.png
fe3c494a3649dedf7085a95e464937d5.png

报文段 长度 作用
序号字段Seq(sequence number field) 32Bit Bit=2^1数据的最小单位
确认号字段acknowledgment number field 32Bit Seq和ACK都是用来实现数据可靠传输的
接收窗口字段 16Bit 流量控制
首部长度指端 4Bit 指示TCP首部长度,TCP首部长度是可变的
URG 1bit 指示报文段中存在着被上层实体置为”紧急“的数据
ACK 1bit 指示确认字段中的值是否有效
PSH 1bit 指示接收方立即将数据交给上层
RST 1bit 连接重置
SYN 1bit 建立连接
FIN 1bit 断开连接

三次握手,4次挥手

TCP建立和释放连接,都要使用的seq序列号和ack确认号,seq序列号和ack确认号是用来实现连接的准确性,确认好都是收到消息的序列号+1,然后发送特定格式的报文来实现连接,报文的格式就是由报文的标志字段来控制,比如建立连接就是SYN=1,和发送序列号,然后目标主机回应。。。(见图),注意前两次握手SYN=1,是不带数据的,第三次则可以带数据。

三次握手

SYN攻击

在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态.
Syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
Syn攻击是一个典型的DDOS攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击
netstat -n -p TCP | grep SYN_RECV
一般较新的TCP/IP协议栈都对这一过程进行修正来防范Syn攻击,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等.
但是不能完全防范syn攻击。

四次挥手

问题回答

  • 1.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
    这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

  • 2.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?

其一,保证发送的ACK会成功发送到对方,如何保证?我觉得可能是通过超时计时器发送。这个就很难用代码演示了。
其二,报文可能会被混淆,意思是说,其他时候的连接可能会被当作本次的连接。

(1)可靠的实现TCP全双工链接的终止。

这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

(2)允许老的重复的分节在网络中消逝。

假 设在12.106.32.254的1500端口和206.168.1.112.219的21端口之间有一个TCP连接。我们关闭这个链接,过一段时间后在 相同的IP地址和端口建立另一个连接。后一个链接成为前一个的化身。因为它们的IP地址和端口号都相同。TCP必须防止来自某一个连接的老的重复分组在连 接已经终止后再现,从而被误解成属于同一链接的某一个某一个新的化身。为做到这一点,TCP将不给处于TIME_WAIT状态的链接发起新的化身。既然 TIME_WAIT状态的持续时间是MSL的2倍,这就足以让某个方向上的分组最多存活msl秒即被丢弃,另一个方向上的应答最多存活msl秒也被丢弃。 通过实施这个规则,我们就能保证每成功建立一个TCP连接时。来自该链接先前化身的重复分组都已经在网络中消逝了。

    1. 为什么不能用两次握手进行连接?

我们知道,3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

本博客为Swagger-Ranger的笔记分享,文中源码地址: https://github.com/Swagger-Ranger
欢迎交流指正,如有侵权请联系作者确认删除: [email protected]

猜你喜欢

转载自www.cnblogs.com/Swagger-Ranger/p/10670961.html