TCP没那么难吧?这篇一定要看
大流程看起来就是这样,也不难理解。不过仔细想想,还是有不少问题得考虑的。比如状态问题,既然TCP是网络通讯,会发生延迟,那么在“信息已经发送,但还没有收到确认”的时候,应当是有个明确状态的,否则会发生状态的错乱。实际上TCP也确实做到了这点,它背后有一台完整的状态机,确保每时每刻,每个动作发生之后,状态都完全可控,一切尽在掌握,不会出现任何“孤点”和“断头路”。 ![]() 上图是TCP的状态转移图的局部,覆盖了建立链接的状态,感兴趣的读者可以按照自己实地走走看(说个题外话,“自己模拟在图上走走”看起来土,其实高科技领域也挺常用。设计波音737的时候,开始大家都不知道发动机怎么摆比较好,设计师乔·萨特就在纸上画出机身和发动机的模型,把发动机模型剪下来在飞机各处摆放,最终发现吊在翼下最合适)。 我在之前关于软件设计的文章里几次提到状态图、状态转移函数,无论是用户生命周期、订单流转过程,都可以用这个工具来解决。遗憾的是,我发现还有许多设计人员不懂得或者不习惯用使用它,实在很可惜。 回到TCP建立连接的过程,我们还要注意ISN。在建立连接时必须先确定ISN,通过它把客户端和服务器的计数对齐。通常的教材上说,ISN是随机生成的,这样就保证了唯一性。 随机的目的是保持唯一,但千万不要以为“随机就不会重复”,简单的“取随机数”是很容易碰撞的。所以传统的“随机”方案是维护一个时钟和一个32位的计数器,时钟每过4毫秒,计数器自增1。因为2^32毫秒就是差不多4个半小时(MSL,Max Segment Lifetime),这基本超出了任何数据包在网络中的可能传输时间,所以可以认为这种ISN是独一无二的。 但这种方案也有风险,既然这样的ISN是连续的,那么中途的恶意程序可能能够预测ISN的生成规律,从而伪造ISN…… 总之ISN的生成是个有趣的设计问题,这里不展开了,有兴趣可以自己搜索资料阅读。 我在开发中遇到不少程序员,一旦需要避免重复,就想到“生成随机数”,根本不管随机数也可能碰撞。更有甚者,一旦遇到类似ISN的场合,就想当然把初始值设定为0,真是让人欲哭无泪(有没有想过ISN为什么不能设定为0呢,欢迎留言讨论)。 说完了建立连接的握手,我们再来看终止连接的挥手。通常大家都知道,TCP是“三次握手,四次挥手”(虽然我很不赞成“次”,但既然它已经约定俗成,这里还是延用通用的说法吧)。那么,为什么要四次才能挥手呢? 知道这个答案的人比能讲清楚“三次握手”的要多。通常的答案都是:TCP是双向通讯协议,要结束连接,双方都必须发送终止信号,告诉对方后续再没有数据发过来了,并等待对方确认,所以一共需要2+2=4次。 ![]() (编辑:惠州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |