[模拟QQ聊天]_[一方客户端断网的情况下,消息怎么处理机制]

liuhuili23 2013-06-18 05:08:26
情景:
实现类似于QQ的聊天,两个客户端聊天时,一个客户端发一条消息要经过服务端,再由服务端把消息发送给另一个客户端,通过这样的一种方式实现两个客户端的通信。
问题:
但聊天时,一个客户端忽然断网了,服务器不能及时的检查出客户端已经连接失效了,这中间有个延迟。这样会导致消息的丢失,针对这个问题服务器端实现了对消息的保存机制,可以把消息保存发送到客户端下次登录。
为了能确定哪条消息被客户端已接受了,哪条信息要被保存到服务器等客户端下次登录时发送,我实现了一发一答的方式来确定消息是否已经已经被接受了,但这样通信太频繁了,请问各位大侠有没更好的方案
...全文
2467 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2014-12-19
  • 打赏
  • 举报
回复
搜“jabber”
bear234 2014-12-19
  • 打赏
  • 举报
回复
TCP要一直保持连接状态 代价很大 而且不现实 网络的物理距离一旦太远了 即使用tcp协议 也不可能保证时刻都处于连通状态 可能电压哪里不稳一下都会导致断开 所以qq一般用UDP实现聊天 离线发送信息什么的的时候才会用到TCP 服务器通过打洞机制让两个机器互相连通 不负责转发信息 否则腾讯的服务器非爆炸不可 根本忙不过来 由于UDP是不可靠连接 所以qq服务器会规定一个时间段 比如5秒 每5秒分别让两个客户端给服务器发回一个udp数据包 这个udp数据包叫心跳包 因为就像人的脉搏一样 服务器通过每隔几秒发送和接受心跳包来确定客户端是否在线 当你发送离线信息的时候,或者服务器已经检测到一个客户端离线后,你的离线发送的信息才会被存储到服务器端,当那个客户端再上线的时候,由服务器通过TCP发送给它 我们可以通过两个现象来证实心跳包的存在: 一个是当对方说“我下线了”的时候,有时候你会等号几秒才会看到对方头像变灰,这几秒除了网络本身的延迟外,就是心跳包的间隔时间了 还有一个就是当你和一个人说话的时候,假如他突然掉线了,而你恰好在他掉线的时候发了好几条信息,那么你会再几秒后才会受到服务器提示,说前面那些信息对方没有收到 这也是因为心跳包有个时间间隔 当然我上面说的也只是粗浅的理论 实际上qq聊天是用tcp和udp都用到了 而且肯定比我说的要复杂 这里还有视频聊天和文件发送的事情 我觉得你要是想模拟下qq聊天 能把心跳包做出来然后实现了离线检测、离线信息存储、发送离线信息和两边聊天这几个功能就足够了 用tcp做个聊天很无聊 很简单 而且实际上没太大意义 分分钟就搞定了----可能局域网里可以用tcp做个简单的聊天还行 在internet里用tcp代价太大 服务器也得累死 几亿人同时聊天啊 哪儿那么简单就实现了.....
yangyunzhao 2014-12-19
  • 打赏
  • 举报
回复
不用心跳检查掉线吗?
hlx_beat 2014-12-18
  • 打赏
  • 举报
回复
QQ聊天会经过服务器?
赵4老师 2013-08-29
  • 打赏
  • 举报
回复
SerialNo SessionNumber
雾雨峰 2013-08-29
  • 打赏
  • 举报
回复
TCP的话不用这么复杂! UDP的话可以在服务器做一个消息缓冲,存储最近的几条信息为消息发送失败对方网络通信异常时的重发。
max_min_ 2013-08-06
  • 打赏
  • 举报
回复


基于QQ消息其实 加外了一层协议的 UDP 协议,

消息通过UDP发送,但是自己添加收到消息确认回复!



huajingze 2013-08-06
  • 打赏
  • 举报
回复
楼主,你好,看过你在一个博客的留言,大致意思是使用一个第三方C接口库,有一个函数要传人回调函数作为参数,这个回调函数有一个void *参数来传入自己的数据;我目前也遇到这样的问题,就是把typedef void (*FunctionType_Status)(int, void *); void playback_status_callback(FunctionType_Status func, void *data);转换成winRT格式支持的类型; 不知道你解决这个问题没?解决的话请给我点帮助和建议,非常感谢!!
Defonds 2013-06-20
  • 打赏
  • 举报
回复
TCP 更靠谱,可靠
liuhuili23 2013-06-19
  • 打赏
  • 举报
回复
TCP,但只是把消息交给底层,并不知道消息是否发出去了
liuhuili23 2013-06-19
  • 打赏
  • 举报
回复
但在客户端一次发送对多个消息的确认,使用窗口确认并不能在网络异常的情况下能够有效判断哪几条信息发送失败了。看来只有使用窗口确认,频繁的进行确认了,或者对tcp修改,因为tcp有别人封装了,想在这个基础上方案上修改
赵4老师 2013-06-19
  • 打赏
  • 举报
回复
《TCP/IP详解卷一:协议》
www_adintr_com 2013-06-19
  • 打赏
  • 举报
回复
引用 2 楼 liuhuili23 的回复:
TCP,但只是把消息交给底层,并不知道消息是否发出去了
TCP 可以通过禁用缓冲的方式来发送, 这样只要 send 函数返回成功, 对方就一定是收到了的.
白行峰 (花名) 2013-06-19
  • 打赏
  • 举报
回复
既然是tcp协议,那么肯定是有3次握手的过程,既然握手是必须的,那么看接口那里是否有返回值。建立连接后每次发送数据都可以确认的吧,不然就不会说tcp是可靠的传输协议了。对tcp,udp用的比较少,如果是我的话我会编写一些底层代码模拟tcp通讯过程来考虑,消息确认是必须的,之后考虑的就是消息确认的最佳方案上。 窗口确认 TCP的一项功能就是确保每个数据段都能到达目的地。位于目的主机的TCP服务对接受到的数据进行确认,并向源应用程序发送确认信息。 使用数据报头序列号以及确认号来确认已收到包含在数据段的相关的数据字节。 TCP在发回源设备的数据段中使用确认号,指示接收设备期待接收的下一字节。这个过程称为期待确认。 源主机在收到确认消息之前可以传输的数据的大小称为窗口大小。用于管理丢失数据和流量控制。 http://baike.baidu.com/view/32754.htm?fromId=1240122
羽飞 2013-06-19
  • 打赏
  • 举报
回复
每一个消息都有一个message id,当服务器向客户端发送消息时,保存下来,直到收到客户端返回这个消息的message id应答 如果消息发送频繁,客户端可以一次发送对多个消息的确认 还有一种类似于TCP的窗口机制,每个消息都是按照递增的编号发送的,客户端发送一个确认消息,这个消息编号之前所有的消息进行确认。我的表达能力不太好,不过楼主可以网上搜索一下TCP窗口机制,肯定可以明白。
www_adintr_com 2013-06-18
  • 打赏
  • 举报
回复
你用的 TCP 还是 UDP? TCP 已经包含了收包确认机制了.

5,529

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧