被程序员误解的TCP
1.关于ACK
今天一个程序员拿着用wireshark抓到的数据包给我看,嗯?程序员还会用这个软件,厉害了,厉害了,看来我得认真对待,包如下所示:
他说http协议都是一个请求,然后会对应有一个回复,但是他抓到的tcp却不是这样,而是好几个请求之后才会有一个ACK,是不是tcp丢包了?
还好,还好,问题不大,问题不大,这个问题我正好知道!其实没有丢包,http就是一个请求对应一个回复,所以很多做网站开发的程序员就自然而然的认为tcp也是这样,其实tcp却不是这样,并不是tcp丢包了,而是tcp并不一定非要采用一问一答的方式,tcp可以延迟确认,就是隔很多包才应答ACK一次,这个ACK隐含了“在此之前的其它包都已经收到”,这样做是为了节省流星,一般电脑系统,无论是windows还是linux都是这样,不同的操作系统有不同的喜好,比如我的虚拟机是这样的,如下图所示:
如上图,通过ACK的频率看上去,看上去差不多是一问一答的,但有时候它会采用将最后4个应答包合并成一个,这样比较节省流量。就像四次挥手,有时候是四次,有时候就是三次,并不固定。
但是安卓系统却不是这样,安卓系统的tcp还是采用一问一答的方式,不信你可以自己抓个包看看,我试了一下,当我在安卓手机打开一张高清美女图片时,发现每收到一个包,都会回复一个ACK,这也太浪费流量了!
2.关于TCP效率低的问题
运维和程序员的知识是互补的,能给我们带来很多启示。
两个程序员在聊天,说道TCP的效率不如UDP的效率高,有一个程序员说TCP需要确认包,而UDP不用确认包,可以一直不停的发,所以UDP效率比较高,赢得周围开发人员和测试妹子的赞赏的目光,可事实真是如此吗?
我们可以假设一个工作场景类比TCP的工作方式,有大量的货物需要从A运送到B,如果只用一辆车来运的话,路上就只有一辆车来回跑(回程相当于ACK包),效率确实低,但不要忘了,tcp有发送窗口字段,只要窗口足够大,就相当于增加货车的数量,TCP也就不受往返时间的约束而源源不断传输数据。
当然TCP确实也有因为往返时间降低效率的时候,比如传输一个很小的数据,比如DNS查询,如果用TCP的包就太浪费了,因为TCP仅头部就40个字节,杀鸡不用牛刀,用水果刀就行,用UDP就行。