本文只是为了便于理解,做非常宽泛的描述,措辞不甚严谨,不当之处还望指正,感谢。
看本文章之前,建议对OSI模型已经TCP/IP不太了解的同学们,看看我之前写的
白话解释 OSI模型,TLS/SSL 及 HTTPS更多内容:
个人博客
一切为了传输 UDP vs TCP
互联网之所以伟大的原因之一是解决了远距离可靠传输信息的问题,既然要进行“互相”传输数据那么肯定是有一定的规则和协议的,TCP和UDP就是两种广泛应用的传输协议,在这里做一个简单的比较:
- UDP (你把它想象成平邮信件),往往邮递员会集中把信件放在邮局,比如一个学校的邮政,但是这种方式不可靠啊,因为这种平邮的信件老是容易“丢包”,也就是说,这种传输方式没法确保收件人一定能收到信件。
这不行啊,所以,人们就想到了一种更为可靠的传输方式:
- TCP(你把它想象成快递),快递员可以直接送货上门,即使不送货上门,可要给你打电话,检查你的身份证,让你签字等等,确保你的包裹不会被丢失。所以,这种方式更“可靠”。
TCP vs UDP 谁更可靠
上面的例子也已经很清楚的看到,tcp(快递)之所以可靠,是因为有种种的“检查”机制,当快递的“包裹”真正到达收件人手里的时候,这个”传输“过程才算完成,否则快递小哥就“重新投递“。那么”UDP“(平邮信件)就不管这一套,反正根据信件上的地址把”传输的信件包“扔在最近的邮件或者上面所写的信箱中就完事,至于随后包裹到底到没到收件人手中,这个UDP不管了。
所以,到现在,我们知道了,tcp传输数据比udp更加“可靠”!
TCP存在之于”互联网“的意义
我们现在能在互联网上看文章,直播,视频,娱乐,购物,甚至网上转账,当然,看直播的话,UDP协议还是不错滴,但是,如果涉及到金钱或者敏感数据,如果都像没有一套“可靠”的传输协议,谁还敢在网上“转账”,“存储信息”呢?
我们已经知道了,TCP存在的意义之一就是:”可靠的传输“,但同时要进行远程通信,”高效的传输“是必不可少的,最后,数据包在混沌险恶的互联网中穿梭,”安全的传输“是必须的。
所以,小结一下,TCP存在之于”互联网“的意义有三点(重要的事情说三遍):
- 让数据进行”可靠“,”高效“,”安全“的传输
- 让数据进行”可靠“,”高效“,”安全“的传输
- 让数据进行”可靠“,”高效“,”安全“的传输
请注意:这里所说的”高效”只是相对TCP自己而言,因为这个”高效“会和后面我们会说到三次握手其中的第二步合并的握手相关,所以我在这里提一下,其实,UDP会因为没有了一些检测机制会比TCP更加高效,快速。
一定的代价
都说”鱼和熊掌不能兼得“,对于TCP来说更是如此,既然选择了”可靠“,”高效“和”安全“作为己任,那么就必然要想一些办法让自己满足这些特征,那么TCP怎么办的呢?
可靠
数据的可靠性意味着接收方接收到了准确无误的信息,如果中间有丢包,要有一定的机制让发送方重新发送。TCP怎么办的呢?它是这么办的:
发送方通过一定方式告诉接收方,所传输的数据包有多大,然后分几次,比如:数据包总共100kb,然后分10次发送,这时候接收方就知道总共有10个数据包,同时发送方会在每个数据包上标记上号码,然后tcp从数据包1开始接受,逐次加一,知道接收到第十个结束,只有这10个全部确认收到了,接收方才确认这个通信完成,所以确保了数据的可靠性。
那么问题来了,接收方怎么知道数据包共100kb,然后又怎么知道什么时候开始算是接受这个包?什么时候接受完成呢?这个时候就是第一次握手的开始,也可以说是第一次交流的开始。
比如:张三(发送方)要发信息给李四(接收方)。
1. 张三:hi,李四,我想发送一个100kb的数据包,打算分10次发送,你那边能接一下么?
2. 李四:好的,收到,你发吧。
3. 张三:ok, 太棒了!
4. 张三:数据包1..2..3..4...5..6..7..8..9..10
那么,可不可以不打招呼直接发?也就是一次握手。当然可以,就像UDP平邮似的,发呗,只不过有可能接收方收不到信息而已,发送方也不知道接收方收到还是没收到,就是得不到保障而已。
安全
大家有没有觉得有什么问题呢? 安全问题! 如果上面第四步张三在给李四发的时候,数据包编号每次总是从1开始,那么岂不是太容易被猜测?如果这样的话,”黑客小黑“可以在与此同时发送带有同样编号的数据包,反正编号都从1开始,猜呗,因为TCP很傻,所以只要是编号相同就接受了,那样就不太安全,黑客就可以猜到这些数据包的编号了。
这里说的数据包编号,其实是在TCP头信息中的”序列号“(sequence number),上面这种攻击方式叫做:TCP序列号预测攻击(TCP_sequence_prediction_attack)
所以,为了防止序列号被踩到,我们引入一种随机序列号的方式进行提高,就是在张三和李四第一次握手的时候,张三同时在数据包中加入一个随机序列号,发送给李四,然后因为李四收到张三的请求信息后还需要发送确认信息回给张三,这时候,李四就成了发送方了,所以李四也需要随机出一个序列号给张三,为的也是张三那边能够安全可靠的得到李四的信息,这里我们看到,在第二次握手的时候,李四需要:
- 确认张三的请求
- 发送自己的随机序列号
本来是两个步骤的,但是,tcp为了”相对高效“的传输,就把这两步”整合“到了一步中了,然后最后一步就是,张三收到来自李四的“确认”以及“随机序列号”,然后再给李四发回一个“确认”消息,至此,三次握手结束,信息传输就开始了。
所以我们把上面的栗子改进提高一下,就变成了:
1. 张三:hi,李四,我想发送一个100kb的数据包,打算分10次发送,为了防止别人猜我发的数据包编号,这是我随机出来的一个初始序列号,9381921,你那边能接一下么? (SYN)
2. 李四:好的,收到(ACK),这是我随机出来的初始序列号,2342322,你发吧。(SYN)
3. 张三:ok, 太棒了!(ACK)
4. 张三:数据包9381921
5. 李四:收到数据包9381921,序列号:2342322
6. 张三:数据包9381922
7. 李四:收到数据包9381922,序列号:2342323
...
大家请注意上面我在对话中标注的:SYN及ACK,就是tcp三次握手的过程:
- 发送方给接收方发送SYN信号
- 接收方确认并回复给发送方SYN/ACK信号
- 发送方给接收方发送确认ACK信号
为什么TCP需要三次握手
我相信大家已经对上面三次握手流程有了一个比较清晰的认识了,那么,我们现在回到文章的主题,为什么TCP需要三次握手呢?为什么不是一次,两次或四次呢?我不妨用一个问句来回答这个问题吧:如果是一次,两次或四次,怎么才能保证TCP的“可靠”,“安全”及“高效”的传输呢?
如果你有了这个问题的答案,那么请一定告诉我!! ;)