2.2 TCP/IP协议与Socket
TCP/IP协议通常放在一起来说,不过它们是两个不同的协议,所起的作用也不一样。IP协议是用来查找地址的,对应着网际互联层,TCP协议是用来规范传输规则的,对应着传输层。IP只负责找到地址,具体传输的工作交给TCP来完成,这就像快递送货一样,货单上填写地址的规则以及怎么根据填写的内容找到客户,这就相当于IP协议,而送货时要先打电话,然后将货物送过去,最后客户签收时要签字等就相当于TCP协议。
TCP在传输之前会进行三次沟通,一般称为“三次握手”,传完数据断开的时候要进行四次沟通,一般称为“四次挥手”。要理解这个过程首先需要理解TCP中的两个序号和三个标志位的含义:
□seq:sequence number的缩写,表示所传数据的序号。TCP传输时每一个字节都有一个序号,发送数据时会将数据的第一个序号发送给对方,接收方会按序号检查是否接收完整了,如果没接收完整就需要重新传送,这样就可以保证数据的完整性。
□ack:acknoledgement number的缩写,表示确认号。接收端用它来给发送端反馈已经成功接收到的数据信息的,它的值为希望接收的下一个数据包起始序号,也就是ack值所代表的序号前面数据已经成功接收到了。
□ACK:确认位,只有ACK=1的时候ack才起作用。正常通信时ACK为1,第一次发起请求时因为没有需要确认接收的数据所以ACK为0。
□SYN:同步位,用于在建立连接时同步序号。刚开始建立连接时并没有历史接收的数据,所以ack也就没办法设置,这时按照正常的机制就无法运行了,SYN的作用就是来解决这个问题的,当接收端接收到SYN=1的报文时就会直接将ack设置为接收到的seq+1的值,注意这里的值并不是校验后设置的,而是根据SYN直接设置的,这样正常的机制就可以运行了,所以SYN叫同步位。需要注意的是,SYN会在前两次握手时都为1,这是因为通信的双方的ack都需要设置一个初始值。
□FIN:终止位,用来在数据传输完毕后释放连接。
整个传输过程如图2-2所示。
图2-2 TCP传输过程图
图中上部为三次握手,下部为四次挥手,这里的四次挥手中画的是客户端提出的终止连接,在实际传输过程中也有可能是服务端提出终止连接,它们的处理过程都是一样的。TCP的传输是双全工模式,也就是说传输的双方是对等的,可以同时传输数据,所以无论连接还是关闭都需要对双方同时进行。三次握手中前两次可以保证服务端可以正确接收并返回请求,后两次可以保证客户端可以正确接收并返回请求,而且在三次握手的过程中还使用SYN标志初始化了双方的ack值。四次挥手就是双方分别发送FIN标志来关闭连接并让对方确认。
三次握手和四次挥手保证了连接的可靠性,不过凡事有利就有弊,这种模式也有它的缺点,首先是在传输效率上会比较低,另外三次握手的过程中客户端需要发送两次数据才可以建立连接,这种特性可能被一些别有用心的人利用,比如,发出第一次握手(并接到第二次握手)后就不回应第三次握手了,这时服务端会以为是第二次握手的数据在传输过程中丢失了,然后重新发送第二次握手,默认情况下会一直发送五次,如果发送五次后还收不到第三次握手则会丢弃请求,如果是个别这种请求当然也没什么关系,可凡事就怕一个多字,当有大量这种请求时就麻烦了,这时服务器就会浪费大量的资源甚至可能导致无法处理正常的请求,这就是DDOS攻击中的SYN Flood攻击,对于这种攻击的一种应对方法是设置第二次请求的重发次数(tcp_synack_retries),不过重发的次数太小也可能导致正常的请求中因为网络没有收到第二次握手而连接失败的情况,具体设置为多少合适,还需要根据实际情况判断,当然如果资金充足也可以使用硬防。
用于传输层的协议除了TCP还有UDP,它们的区别主要是TCP是有连接的,UDP是没有连接的,也就是说TCP协议是在沟通好后才会传数据,而UDP协议是拿到地址后直就传了,这样产生的结果就是TCP协议传输的数据更可靠,而UDP传输的速度更快。TCP就像是打电话,需要先拨通对方号码才能通信,而UDP就像是使用对讲机,拿起来就可以直接讲话。通常视频传输、语音传输等对完整性要求不高而对传输速度要求高并且数据量大的通信使用UDP比较多,而邮件、网页等一般使用TCP协议。
HTTP协议的底层传输默认使用的是可靠的TCP协议,不过它对互联网的高速发展带来了很大的制约,Google制定了一套基于UDP的QUIC(Quick UDP Internet Connection)协议,这种协议基于TCP和UDP之间,不过现在还没有广泛使用。
TCP/IP协议只是一套规则,并不能具体工作,就像是程序中的接口一样,而Socket是TCP/IP协议的一个具体的实现,第3章给大家介绍Java中Socket的具体用法。