之前做过局域网的聊天软件,现在要做运行在广域网的聊天软件。开始接触网络编程,首先是接触到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。客户端也属于分布式应用程序,具有一些服务端的功能 在进行语言,视频,文件传输的时候,可由服务端协调 在两个客户端直接进行点对点通信

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

即时通信 选择UDP还是TCP协议的更多相关文章

  1. Python基础教程之udp和tcp协议介绍

    Python基础教程之udp和tcp协议介绍 UDP介绍 UDP --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议.UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但 ...

  2. Java第三阶段学习(八:网络通信协议、UDP与TCP协议)

    一.网络通信协议 1.概念: 通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传 ...

  3. 通信协议之HTTP,UDP,TCP协议

    1.UDP,TCP,HTTP之间的关系 tcp/ip是个协议组,它可以分为4个层次,即网路接口层,网络层,传输层,以及应用层, 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协 ...

  4. day28——C/S与B/S架构、网络通信原理、osi七层协议、UDP、TCP协议、TCP的三次握手与四次挥手

    day28 C/S B/S架构 C:client 客户端 B:browse浏览器 S:server 服务端 C/S C/S架构:基于客户端与服务端之间的通信 ​ QQ.游戏.皮皮虾 ​ 优点:个性化设 ...

  5. python网络编程——使用UDP、TCP协议收发信息

    UDP UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送. UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内. UDP ...

  6. 使用UDP和TCP协议的各种应用和应用层协议

    IGMP和ICMP是传输层协议

  7. 移动端IM系统的协议选型:UDP还是TCP?

    1.前言 对于有过网络编程经验的开发者来说,使用何种数据传输层协议来实现数据的通信,是个非常基础的问题,它涉及到你的第一行代码该如何编写. 从PC时代的IM开始,IM开发者就在为数据传输协议的选型争论 ...

  8. 协议森林08 不放弃 (TCP协议与流通信)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! TCP(Transportation Control Protocol)协议与IP ...

  9. TCP协议与流通信

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! TCP(Transportation Control Protocol)协议与IP ...

随机推荐

  1. python 的排名,已经python的简单介绍

    我在今天看了一篇文章,是简书的全网程序猿写的,Java已经退出神坛,python稳居第一. python是由龟叔写的,它在英文的意思是蟒蛇. 根据编程语言流行指数排行榜2019年2月的榜单 据了解,目 ...

  2. Linux监控平台、安装zabbix、修改zabbix的admin密码

    1.Linux监控平台 2. zabbix监控 3.zabbix的安装下载:wget -c https://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbi ...

  3. Linux下修改Jenkins默认端口

    我是自动安装的Jenkins,默认目录为 jenkins安装目录:/var/lib/jenkins jenkins日志目录:/var/log/jenkins/jenkins.logjenkins默认配 ...

  4. hdu 2095 find your present (2) 位运算

    题意:找出现次数为奇数的数 xor运算 #include <cstdio> #include <iostream> #include <algorithm> usi ...

  5. 《DSP using MATLAB》Problem 7.9

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  6. python写service时全局变量问题

    在尝试用flask写service的过程中,我发现全局变量使用虽然很方便,但其实是很冒险的. 本次我使用的是声明global变量的方式,如果作为本地的单次使用的程序来说,确实没有问题并且很好用,对于竞 ...

  7. 爬虫-day01-基础知识

    '''爬虫的构成下载器: 抓取页面 urllib equests selenium + webdriver解析器: 解释并提取页面元素 BeautifulSoup4 PyQuery Xpath Reg ...

  8. NPOI导出excel(2.0.6版本)

    public static void WriteExcel(System.Data.DataTable dt,string fileName) { NPOI.XSSF.UserModel.XSSFWo ...

  9. MySQL 5.7临时表空间

    MySQL 5.7起,开始采用独立的临时表空间(和独立的undo表空间不是一回事哟),命名ibtmp1文件,初始化12M,且默认无上限. 选项 innodb_temp_data_file_path 可 ...

  10. linux怎么样显示命令历史后又显示命令的输入时间

    linux的bash内部命令history就可以显示命令行的命令历史,默认环境执行 history命令后,通常只会显示已执行命令的序号和命令本身.如果想要查看命令历史的时间戳,那么可以执行: 临时显示 ...