我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
归档 2013 年 6 月

笔记:对比TCP与UDP

TCP和UDP是传输层最常用的两种协议,几乎每个应用层协议都要在它们中间选择一个。同样,本文不详述其协议本身,而是着重对比。

显然如果我要是说,TCP是面向连接的可靠传输协议,而UDP无连接且不可靠,那么我这半个月的书算是白读了。

UDP仅仅是在IP的基础上提供了多路分解和多路复用,以及差错校验,十分简单——从UDP报头就能看出。

而TCP提供的功能则要复杂得多,首先为了保证数据能够正确、有序地到达,TCP使用了“流水线”“积累确认”的模型。

TCP会对每个数据报进行编号,同时在每个数据报中,都包含一个“确认序列号”的字段,用来指明上一个从对方正确接收的数据报。一旦接收方在一定时间内没有发送相应的确认序列号,那么发送方就会重传这些数据报。

数据报的发送行为是“流水线”(与之对应的是“逐一确认”)的,即发送方不逐一等待确认,而是一次发送若干个数据报,换句话说,发送和确认的行为是异步的。

而在这里,确认行为是“积累”(与之对应的是“选择重传”)的,也就是说,一旦一个数据报丢失了,那么在这之后的所有数据报都会重传。

TCP还提供有流量控制和拥塞控制的功能。

流量控制即在每个数据报中,都会指明自己的缓冲区还能容纳多少数据,发送方将根据这个值来协调同时存在于“流水线”上的数据量。流量控制保证了,应用层程序不会因为缓冲区不足而无法接收到新数据。当缓冲区满了以后,发送方会暂停发送。

拥塞控制即TCP会根据网络情况,自动调整发送速率。典型策略是每发送成功一个包,即提高一些发送速率,每出现一次重传,即降低一些发送速率。

同时TCP还使用了“慢启动”模型,即建立连接后默认速率是最低的(1MSS/RTT, MSS即最小TCP分段, MTU减去TCP报头), 然后逐渐提升发送速率。

这样可以保证重传行为始终是受控的,不会因为网络不稳定而出现大量重传的数据报而堵塞线路。

TCP往往用于要求数据分毫不差的应用中,比如网页(HTTP), 文件传输(FTP), 电子邮件(SMTP/POP3), 终端(Telnet)等等。

而UDP往往用于可以容忍数据丢失的协议,如流媒体应用, 语音和视频通话等,这些应用即使出现数据丢失,影响也是瞬间的,可以容忍的。

那么为什么这些流媒体应用要选择UDP呢?换言之,TCP在保证可靠传输的同时又牺牲了什么呢?

对于流媒体应用,临时的数据丢失是可以容忍的,但绝不能容忍的是延迟。

为了建立一个TCP连接,TCP需要进行“三次握手”,只有当三次握手完成后,才会正式传输数据。这样一来,建立连接并传输一份数据,至少需要2个RTT(往返延迟), 如果考虑发送端确认的话,那么需要2.5个RTT.

在断开连接时,TCP还需要“四次挥手”,又会消耗掉至少1.5个RTT.

UDP则没有这个顾虑,直接发送数据,只需0.5个RTT.

UDP协议本身保证了,当应用层通过Socket将数据传递给传输层时,UDP会立刻将数据报发送出去。而TCP不提供这个担保,TCP因为提供有流量控制和拥塞控制服务,TCP会自行选择在“合适”的时候再发送数据报。

流媒体应用在需要低延迟的情况下,还需要尽可能的带宽保证。

尤其是因为TCP的拥塞控制服务,注定了TCP不能够尽可能利用带宽,当网络出现堵塞时,TCP的拥塞控制会降低发送速率,让出带宽,直到网络恢复。

而UDP只会简单粗暴地继续发送数据报,很多情况下,TCP都在为UDP让出带宽,这也算是劣币驱逐良币的一种表现,据说有大牛在研究给UDP加上拥塞控制。

总结:那些宁可在UDP上自行实现TCP的部分功能的应用,主要原因在于希望避开TCP的拥塞控制,以便于尽可能地利用带宽。

笔记:对比 HTTP 和 FTP

HTTP和FTP作为互联网架构中相当基本的应用层协议,想必大家对它们都有一些了解,因此,本文不详述其协议本身,而是着重于它们之间的对比。

应该说HTTP和FTP的定位是相当接近的,FTP用于传输文件,而HTTP用于传输本质也是文件的“对象”(不要忘了HTTP还有PUT和DELETE等方法). 它们均基于TCP, C/S架构,均为基于纯文本的“简单”协议,都有SSL版本:HTTPS和FTPS(不是SFTP!).

通常FTP除了文件本身的属性,如体积,修改时间外,没有其他的元信息(meta-data), 而每个HTTP报文则都会携带大量的元信息,即HTTP报头中的键/值对。这估计也是HTTP将文件抽象为“对象”的原因吧。下面是一个简单(大多数浏览器都会产生更多报头)的HTTP请求报头:

GET / HTTP/1.1
Host: jyprince.me
Connection: kepp-alive
User-agent: Mozilla/4.0
Accept-language: zh-cn

之所以我将报头中的键/值对视为“信息”而不是协议本身,是因为它们中的大部分字段都是交由Web服务器或者浏览器来处理的。

当然,也有一些例外,如 Connection: kepp-alive, 这个报头指出客户端希望于服务器建立持久连接。基于持久连接的HTTP, 和FTP一样,都可以认为是一问一答的交互式会话。

但HTTP是无状态的,每一问一答中间,是没有关联的,将多个应答放在同一个TCP连接中仅仅是为了节约建立TCP连接的时间。

而FTP的两个应答之间,服务器是需要维护状态信息的,例如客户端的当前路径,这将直接影响到之后的指令的行为。

HTTP虽然也有手段携带状态信息(如Cookie), 但在我看来,这些属于协议之上承载的信息,并非协议本身。

HTTP报文的数据紧接报头,以一个空行隔开,即HTTP报文中的键/值对(元信息)和数据是一体的。而FTP连接中仅发送控制指令,每当需要传输文件的数据时,会建立另一个连接专用于传输数据。

总结:

  • HTTP在报头中以键/值对携带元信息,FTP没有
  • HTTP无状态,FTP在会话期间维护状态
  • HTTP的元信息与数据一同传输,FTP使用单独的连接传输数据

RootPanel 2.0 Case Close

我最喜欢的,便是在一个项目完成后,写一篇总结性质的日志,可惜这样的机会并不多。

这一段时间,我心里的压力挺大的,更多的是自己给自己的压力吧——我估计那几十名用户可能不大关心新版本什么的吧。不过这压力似乎并没影响我一天拖一天,看新闻,逛论坛,打游戏。

现在,代码已经全部完成,也完成了大部分的测试,只等上线和微调了,但我心里还是很不安。这一次的更新很大,不亚于重新写一个,但准备工作却远不如RP首次上线时充分,仅预留了几天的测试时间,而且这次要迁移的用户要比上次多很多。这种不安直接导致这几天,经常打开论坛,又关上;打开IDE, 又关上;打开游戏,又退出 ….

一开始我没打算为RP2增加这么多功能,但是写着写着,越来越想一步到位。RP2从3月一直拖到了6月,其实只有五月中下旬我在写RP2的代码我会说么?3-4月一直在反复折腾LightPHP, LightPHP在Web领域,可谓是见证了我成长,从我入门PHP两个月,到现在(两年), 我一直在完善它,虽然它现在仍不完美。

一步到位,我想我做到了,在之后的一段时间,RP面板不会有大的更新了,因为这次的架构设计还算不错,应该可以撑很长时间,小修小补就够了。接下来我将着手宣传工作,同时如果Parthas有时间的话,准备开拓一下海外市场。

我也没想到,我的第一桶金竟然是靠卖虚拟主机,想一年半以前,我还在为寻找一个物美价廉的虚拟主机而发愁。说实话,要不是因为面板是我自己写的,我真的不屑于卖虚拟主机,这离我靠卖代码赚钱的目标还有很大差距,不过也许对于现在的网络环境,卖服务才是更好的选择。

附新版宣传稿:

RP主机:技术宅的Linux虚拟主机

可前往官网了解更多:http://rpvhost.net

我是一名高二学生,出售虚拟主机已经一年多了,RP主机也上线半年了。一直觉得 ____ 是一个高质量的社区,所以我一直在学习和完善,直到现在才敢来这里宣传。

在我还是初中生时,我便涉足Web编程,但那时候零花钱少啊,找不到性价比高又能满足需求的虚拟主机——我一直喜欢追一些新鲜的技术。我深知学生党和业余建站党的需求,于是在我现在有能力时,搞出了RP主机。

RP主机本质上是一个严格划分了用户权限的Linux服务器,你可以在这里通过Shell随意运行进程,(以非root权限)自行安装软件和运行时,当然,也有公用的运行时。需要共享的80端口,MySQL,PPTP等服务,则可以通过我自己编写的面板进行自助管理。

RP主机对PHP,Python,Go,NodeJS,C/C++等语言均有非常好的支持。RP主机的服务器来自Linode,LocVPS等VPS提供商,目前有日本和美国两个节点,稍后会新增香港节点。价格8元/月,19/季度。

精子生于 1995 年,英文 ID jysperm.

通过 IPFS 访问

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2026-11-01.