对使用UDP协议和大规模即时通讯的思考

  之前做过局域网的聊天软件,现在要做运行在广域网的聊天软件。开始接触网络编程,首先是接触到TCP和UDP协议

在网上查资料,都是这样描述 TCP面向连接,可靠,数据流 。UDP无连接,不可靠,数据报。但是实际使用的时候就会有很多疑惑了,比如我们做一个聊天软件 客户登陆我们的服务器,我们到底是使用哪一种协议呢 是使用TCP和客户端保持常连接,还是使用UDP这种无连接,数据传输不可靠 还是使用TCP在和客户端交换一次数据后就断开连接 需要的时候再连接。

这是3种情况。这几种情况针对于需要服务器转发的消息,需要客户端之间点对点传输的情况除外

1。使用TCP协议和客户端保持常连接(长连接) 从客户登陆到客户离线,在客户端与服务端之间一直保持着一个TCP连接,两者之间可以随时相互通信,信息的传输是可靠的,这是我们最想看到的方式。但是我们不禁要问了 一台服务器能保持多少个TCP连接呢,这是我一直困惑的,前端时间遇到一个有些经验的程序员 按我的理解,使用这种常连接方式的C/S软件,如果服务器是一台普通的计算机 一般情况下,500多个TCP连接之后就会开始出现问题。对于真正的服务器,我们可以想象它是通过一个网络设备充当网关(类似于路由器,硬件防火墙)连接到公网,服务器连接到网关,服务器对外服务的端口都和网关有映射关系。所以我们客户端知道服务器公网IP和服务端口 可以直接发起TCP连接请求。所有的数据交换都会经过服务器的网关 而这个网关,根据我的了解 它能并发处理500到10W个连接不等,这主要取决于这个硬件防火墙的质量,直接和价格相关。我们一般家里或者寝室使用的路由器都能同时处理几百个连接,使数据几乎是没多少延迟就通过网关了,而服务器的网关我们可以想象 再差也能支持几千个并发连接吧,而在服务器网关背后有可能不止一台服务器,对于大规模的即时通讯软件来说 服务器网关背后肯定是服务器集群,服务端也是分布式的 服务端运行在这个服务器集群的多台服务器中,由多台服务器来对客户端发来的数据进行协同地均衡负载处理,以支持海量用户 处理完成之后通过网关把结果发给客户。我们可以想象,像腾讯QQ之类的大规模即时通讯软件,经常性的是几千万用户同时在线 如果都采用常连接的方式。岂不是要服务器的硬件防火墙监控数千万个连接了,就算分布式服务端能承受这么多用户 网关也受不了,而且有理由相信服务器也受不了 。所以对于大规模即时通讯,尤其是用户数量众多 肯定不能用TCP常连接的方式,这种方式只适合于小规模的即时通讯,如局域网,公司内部的即时通讯等 对于大规模的,用户数量众多的C/S软件 应当采用UDP协议进行数据传输,网关就不停收发数据包就可以了

2。使用TCP协议和客户端进行短命连接,用了就关 比如客户登陆请求好友列表,我们就和他建立TCP连接发给他好友列表,然后关掉连接 当用户要给另外一个客户发信心我们再建立连接,数据传完我们又关掉连接 这种方式,无疑服务器可以承载更多的用户登陆。但是缺点也是非常明显的 一般情况下我们接收的数据都不大,每次发一点点消息都要建立连接 TCP本来就比较消耗网络资源,这样毫无规律的断断连连 连连断断,加上本来这种方式就有较高的延迟 也不适合大规模的即时通讯

3。使用UDP协议与客户端无连接 UDP无连接,不可靠,数据报。无连接,代表了它快速,资源消耗小 接着我们要看“不可靠”,这个不可靠它究竟不可靠到了什么程度呢?事实上,在Internet上传输的UDP包从A发送给B 它完整地到达几率一般情况下还是相当之高的。我们开发一个多用户的即时通讯软件 采用UDP传输消息的时候,报文被划分成包 一个UDP包究竟是多大?经过我的了解一个UDP用户包最大大小是64KB 根据网络状况,实际在传输包的时候可能把包划成若干个分片 一个分片的最大大小是1640B 可以保存好几百个汉字。我们在使用QQ的时候应该也注意到了,我们给好友发送信息的时候都有字数上限的,我的理解这是为了让传输的信息不至于太长而分成多个包,保证所有信息装在一个包里,要么完整发送,要么传输失败。我们客户端向服务端发送的消息 一般来说可以定义一个结构体 这个结构体包含指令 消息正文等要素(见之前写的进程间通信基础知识)我们都知道这个结构体其实很简单,只有几个成员 包括正文,对于一般的文字消息,或者请求 更新好友列表的消息对象被序列化后也很小,一个UDP包被完全可以装下这个序列化后的对象。到这里我们再来看看UDP协议的“不可靠”,“数据报”。UDP协议提供数据报机制传输信息 如果报文比较长,比如一个文件,一个图片 要被划分成若干个数据包,由于对于一般的文字消息和其它指令都是比较小的 它们会被放在一个包里面,由于UDP是无连接的 不可靠的,如果发生丢包,不会重传 所以不能保证数据包能完整并准确地到达目的地,但是对于我们的即时通讯软件来说 一般的聊天信息比较小,比如我们给一个好友发送一条聊天信息“今天我很高兴”,会不会服务器转发的时候只收到“今天我很高”,再传给好友的时候变成了“今天”,答案是不会发生这种情况的 UDP虽然描述是不可靠,不过依然在数据包中包含了头信息描述了包的大小等信息,在包进行转发的过程中 如果数据不完整,是会被网络设备发现的,比如中途一个转发这个包的路由器发现了一个不完整的UDP包会直接丢弃,如果是TCP 当有包被丢弃了会进行重传,对于UDP 包在传输过程中由于数据的缺失被丢弃不会进行重传 我们顶多就是一条信息发送失败了,而这种概率一般情况下是非常低的 。

 

经过以上的一些思考,我得出了这样的结论 大规模即时通讯应当采用UDP协议进行常规的通信,TCP可以作为一种辅助手段

经过一些学习,思考和实践 我得出了心目中的大规模即时通讯软件的总体架构:

1。以UDP协议作为主要数据传输协议

2。服务端使用一个数据库保存信息(分布式数据库)

3。服务端是是分布式的,通过异步多线程技术,集群服务等 通过服务器集群共同运行服务端,对外进行海量信息处理(转发,暂存,广播消息)

4。客户端也属于分布式应用程序,具有一些服务端的功能 在进行语言,视频,文件传输的时候,可由服务端协调 在两个客户端直接进行点对点通信

 

这样的总体架构能够保证大规模即时通讯,更需要做的地方就是对数据的查询优化 服务端的性能优化等。

我的Fox核心将采用这种总体架构中的一部分,为什么说是一部分呢,由于水平所限 并且作为一个学习和进步的手段,根据自身的实际情况 将采用单一的数据库,以及单一的服务端

相信先把这种做好了 相信有一天能真的做到真正的大规模用户的C/S软件。

我觉得一个人思考是很重要的,即时目前做不出来那么好的东西 但是思考会让人产生方向,有了目标,并且心目中有了软件的雏形 我相信不知道自己想要的结果,编程是枯燥无味的漫无目的的,但是心中有了大致的模样 就会产生动力,也会多了很多乐趣

请有经验的老鸟留言教育教育

转载于:https://www.cnblogs.com/yuanfan/archive/2010/12/25/1916420.html

你可能感兴趣的:(对使用UDP协议和大规模即时通讯的思考)