应用重连时间_网络游戏中的断线重连和心跳检测

网络通信是网络游戏的基础模块之一。Socket通信是当下网络游戏中最常见的一种通信方式,本文主要对网络游戏Socket通信中的一个常见问题做一些讨论。

Socket与HTTP

在游戏行业讨论网络通信时,很多人会将Socket和HTTP相提并论,一个称之为长连接,一个称之为短连接。事实上,这种划分方式虽然不能算错,但并不严谨,原因在于,Socket和HTTP其实并不是一个维度上的东西。

HTTP是一种应用层的协议,基础是TCP/IP协议。TCP/IP协议其实并不是单个协议,而是一组协议,包含了TCP、IP、UDP等多个传输层和网络层的协议。

0d3d3cc4cfb5e0d9cbdf2fd3f03f729a.png

一次典型的HTTP请求,包含几个过程:客户端建立连接→客户端发送请求→服务器处理请求并返回数据→关闭连接。通常在流程完成之后连接就会关闭掉,服务器也不会保存连接的任何状态。虽然HTTP协议也支持keep-alive机制,可以不需要重新建立TCP连接,但是在网络游戏中通常不会用到这个属性。

而Socket其实并不是一种协议,而是指一种通信的方式。Socket这个词通常翻译为“套接字”,然而我很不喜欢这种生造出来的翻译。这词儿的原始含义是插座、插口、插槽,我觉得无论哪个都比不知所云的“套接字”要好。

Socket大致上可以理解为一种点对点的通信方式,操作系统为应用程序提供了一系列Socket相关的接口,而应用程序调用相关接口可以更方便快捷地操作数据,与另一个Socket端口进行通信。虽然在网络游戏中Socket通常使用的是TCP协议,实际上Socket也支持UDP,甚至支持自定义协议(Raw模式)。只要是通过操作系统提供的Socket接口进行点对点的数据通信,就叫做Socket。(所以其实Socket翻译成插口插槽还更形象一些)

那么问题来了,HTTP难道不是点对点的吗?那么HTTP和Socket有什么区别呢?答案是这两者本来就没有什么冲突关系,它们并不是一个维度上的说法,就像一个人喜欢吃火锅和这个人是程序员这两者之间没有什么联系。HTTP是网络协议层的东西,而Socket是一种通信方式。

之所以在游戏领域大家通常将HTTP和Socket放在一起说,其实主要指的是短连接和长连接这两种模式。短连接一般使用HTTP协议,只要完成一次数据交换就关闭连接,服务器并不保存连接状态和数据,也没有办法主动向客户端发送消息。而长连接一般使用TCP协议,直接调用Socket接口进行数据通信,在双向流式传输的Socket通信中,双方的地位是对等的,既可以由客户端向服务端发起消息,也可以由服务端向客户端发送消息。

Socket通信的断线重连和心跳检测

既然是网络通信,就一定会遇到网络断线的问题。短连接游戏的处理相对比较简单,收不到正确数据重发即可,本文主要讨论一下Socket长连接中的相应处理。

首先来探讨一个问题:客户端如何知道自己断线了?

通常来说,断线有两种方式,一是主动,二是被动。

Socket连接是可以主动关闭的,服务器或客户端任何一方主动关闭连接对方都会受到相应的消息。

ae3195da3705b05a3ece87cc4eb6e38a.png

当对方主动关闭连接或者发生其他异常时,另一端的recv接口的返回值会小于等于0,这个返回值是即时生效没有延迟的,这时候就知道,对方关闭了连接,在这里可以做相应的处理。比如说客户端主动关闭,服务器收到消息后,可以记录一下用户的离线时间;服务器主动关闭,客户端收到消息可以重新连接或者给用户弹出一些提示“你被踢下线了”之类的。大部分情况下,浏览器的网页刷新、浏览器或app关闭时,都会立刻收到这个消息。当然事无绝对,这一般跟你的应用程序载体(即操作系统或浏览器)有关,也有部分载体没有这个功能,如果没这个功能就得看下面的处理方式了。

另一种情况相对复杂一点,那就是被动断线,一般情况就是断网。碰到断网,Socket是无法马上得知的。那么如何来判断到底有没有断网呢?

大家可以回想一下,在日常使用电脑的时候,是如何判断自己有没有断网的。

相信很多人的第一反应是,打开浏览器,输入baidu.com,如果等了半天浏览器一直是一片空白,那么ok,确定自己断网了。

很多事情的本质其实是一样的,在Socket连接中,碰到断网也是类似的处理方式。最常规的方法就是用心跳包来检测。心跳包的基本原理是,每隔一段时间,一方就向另一方打个招呼,发送一段很小的数据,如果对方有回应,那就OK,如果对方没有回应,那就是断网了。由于这种隔一会儿就来一下判断是不是还活着的方式很像是心跳,所以通常称之为“心跳检测”。

如果Socket使用的是TCP协议,现在的主流操作系统都支持TCP的Keep Alive模式。Keep Alive就是系统帮你封装好的心跳检测,每隔一段时间系统帮你发个空包(注意:空包不代表没有任何数据传输,只是没有任何业务层数据而已,在TCP通信中,即使是空包也是有数据传输的),对面回了说明这条Socket连接还活着,对面没回说明连接已完蛋。

Keep Alive有这么几个参数:

tcp_keepalive_time:系统的心跳包并不是一开始就会发的,而是当TCP连接长时间都没有数据传输时才会发送。打个比方大概就是,如果对方刚跟你说过话,就不必再去检测他是否还活着,当对方好久都没有反应了,你才会去捅捅他问哎兄弟你还活着吗。这个参数就是设置多久没说话才会去询问对方。

tcp_keepalive_intvl:每隔多久发送一次心跳包。前面说过,心跳包是每隔一段时间发送一个,这个参数就是控制间隔的。

tcp_keepalive_probes:重试次数。假如有一次心跳对方没有回复,可能这时候并不能确认连接已经断开,而是会反复尝试几次,几次都没有回复才会确信这条连接已经完蛋。这个参数是控制重试次数的。

系统提供的Keep Alive功能从机制上来说是比较完善的,不过,在实际应用中,一般并不建议使用系统提供的TCP Keep Alive来做心跳检测。原因主要有几个,首先keep alive只有TCP协议才支持,UDP和Raw(自定义协议)模式都是无法支持的;更重要的原因是,整个过程对应用层来说全部是不可控的,对业务来说不够灵活。实际上,了解Keep Alive的原理,自己写一个也是很简单的事情,所以一般建议自己在应用中实现心跳检测的功能。

在网络游戏中,心跳检测和断线重连一般都由客户端发起。客户端每隔一段时间发一个心跳消息,同时去监听服务器回复的消息,如果客户端连续发送了N的消息都没有收到回复,就做相应的处理,比如说在用户无感的情况下默默地重新建立连接,又或者是给用户弹出一个提示告知断网,都是很常见的处理方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值