在页游时代,使用Flash ActionScript 3.0进行开发,as3提供比较简单和健全的socket API。到了手游时代,基于tcp的socket编程遇到了一些棘手的问题。通常情况下手游都要支持至少二大主流平台:Android、IOS,二者共存,暂时没有迹象表现哪一方会没落。

页游跑在浏览器里,所有的连接成功、失败等操作,都可以通过addEventListener进行监听,很方便,一般也不存在频繁掉线的情况。而手游,因为手机的便携性决定了它的移动性,既然是可移动的那就会一定会面临网络不稳定的情况。

client与server通信如果使用TCP逻辑会比较简单一些,但存在一些问题,这个问题在移动平台下暴露的比较明显。QQ客户端使用的是UDP而非TCP,主要原因是因为网络的不稳定性。而TCP和UDP主要区别是什么呢?其实就是长连接与短连接的区别

长连接是比较消耗资源的,但是通常情况下,一方断了另一方会较为及时的收到消息,业务逻辑上是比较简单和及时的。

基于TCP的Socket网络编程,如果想跨平台,通常都使用C/C++进行封装,这样代码层面至少是统一了。但移动设备上面临的主要问题是频繁的掉线,Android好一点,IOS其实是比较麻烦的。下面列一下在Android、IOS设备上HOME、电源键对网络的影响:

平台 Home键切后(网络状态) 电源键(网络状态)
Android Y Y
IOS Y N

其它的2G/3G/4G/Wifi之间的相互切换,也是比较麻烦,必须要重连了(因为客户端的IP已经发生变化了)。

电源键按下时,IOS就锁屏了。Socket就断掉了,但Server端并不会收到Client掉线。问题来了,不是说TCP是长连接吗,我一端掉了那另一端应该收到断开的消息啊,嗯,理论上是这样子的,协议也是这么规定的,但要先注意这样一个问题:

TCP连接使用的是三次握手

TCP断开使用的是四次握手

连接使用三次握手,这个不多说了,主要原因是为了保证二端都能确认连接已经建立(SYN、ACK)。而断开为什么是四次?因为socket是双工(双向通信),相当于存在二条通讯的线路,一条用于接收,一条用于发送。一方主动关闭时(写通道被关闭了,但此时读通道还是正常的),它会发送FIN,另一端收到时会响应FIN+1(表示我收到你的关闭请求啦~),然后另一端处理完自己的逻辑后,告诉发起请求关闭的一方,我同意了你的关闭请求(不会再向你发送数据啦~),此时发起关闭的一方的读通道才是正常被关闭了。发起请求关闭的一方会在2MSL(报文最长生命周期的两倍 Maximum Segment Lifetime)后释放掉它所占用的端口(连接记录此时才会被清除)。

所以,你会发现哇,原来关闭也是需要确认的。假设服务器突然断电了,客户端是不知道服务器端已经无法连接了的,还会认为可以发送数据给服务器端。通常都是使用心跳包进行检测来双方的连接是否还存在。

我尝试过在cocos2dx使用libuv来实现网络通信,感觉异步写起来确实过于繁琐。libuv采用异步回调的写法,所有的回调函数必须是static的。通常一款游戏是有二个socket长连接的:游戏主逻辑、聊天服务器,好在libuv支持回调参数里“夹带自定义参数”,倒也问题不大。不过我遇到一件奇葩的事情是,在三星GTI9000 Android 2.3.6系统上,将游戏切入后台,网络状态由2G变成wifi,不回调socket,调用发送之后也没有触发关闭回调方法,其它能借用到的Android设备都测试过,没什么问题了。wifi切到2G/3G,后台切换至前台后立马触发关闭的回调函数。

后端处理是这样的,建立socket时会随机生成一个密钥串,当客户端断开连接时,拿这个密钥串向服务器进行验证,但是服务器验证时有个特殊的判定,如果请求生成密钥串的客户端IP与重连时的客户端IP不一致,则认为是非法请求。也就是说2G切换至WIFI时,IP变了,服务器其实是直接将连接断开了,但为什么没触发关闭的回调函数,这个或许是那个Android系统版本的bug吧

后来想的办法有二个:

1、针对Android平台,记录连接时的网络类型,然后切换至前台时再获取网络类型,如果发现二次的网络类型不一致就提示需要重新登录游戏了;

2、记录建立连接时的IP地址,当切换至前台再获取IP,如果这二个IP不致,也认为是需要重登录游戏了,因为无论你拿什么密钥串都将无法再登录游戏,服务器认为这个请求是非法的;

移动平台下的Socket几个问题的更多相关文章

  1. .net平台下C#socket通信(中)

    上篇.net平台下C#socket通信(上)介绍了socket通信的基本原理及最基本的通信方式.本文在此基础上就socket通信时经常遇到的问题做一个简单总结,都是项目中的一些小问题,拿来此处便于下次 ...

  2. .net平台下C#socket通信(转)

    上篇.net平台下C#socket通信(上)介绍了socket通信的基本原理及最基本的通信方式.本文在此基础上就socket通信时经常遇到的问题做一个简单总结,都是项目中的一些小问题,拿来此处便于下次 ...

  3. .net 平台下, Socket通讯协议中间件设计思路(附源码)

    .net 平台下,实现通讯处理有很多方法(见下表),各有利弊: 序号 实现方式 特点 1 WCF 优点:封装好,方便.缺点:难学,不跨平台 2 RocketMQ,SuperSocket等中间件 优点: ...

  4. .net平台下C#socket通信(上)

    在开始介绍socket前先补充补充基础知识,在此基础上理解网络通信才会顺理成章,当然有基础的可以跳过去了.都是废话,进入正题. TCP/IP:Transmission Control Protocol ...

  5. 一步一步从原理跟我学邮件收取及发送 4.不同平台下的socket

    既然是面向程序员的文章那当然不能只说说原理,一定要有实际动手的操作.    其实作为我个人的经历来说,对于网络编程,这是最重要的一章! 作为一位混迹业内近20年的快退休的程序员,我学习过很多的开发语言 ...

  6. .net平台下socket异步通讯(代码实例)

    你应该知道的.net平台下socket异步通讯(代码实例) 1,首先添加两个windows窗体项目,一个作为服务端server,一个作为客户端Client 2,然后添加服务端代码,添加命名空间,界面上 ...

  7. BEA WebLogic平台下J2EE调优攻略--转载

    BEA WebLogic平台下J2EE调优攻略   2008-06-25 作者:周海根 出处:网络   前 言 随着近来J2EE软件广泛地应用于各行各业,系统调优也越来越引起软件开发者和应用服务器提供 ...

  8. Android平台下的TCP/IP传输(客户端)

    在工科类项目中,嵌入式系统与软件系统或后台数据库之间的信息传输是实现“物联网”的一种必要的途径,对已简单概念的物联网,通常形式都是一个单片机/嵌入式系统实现数据的采集及其处理,通过蓝牙,wifi或者是 ...

  9. [转]Windows平台下Makefile学习笔记

    Windows平台下Makefile学习笔记(一) 作者:朱金灿 来源:http://blog.csdn.net/clever101 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译 ...

随机推荐

  1. 随手复习一下委托:delegate

    先骂个街,天儿太闷了…… 随手复习一下委托,delegate 是一种函数指针,是 .net 提供的一种安全的函数指针,翻译的也很贴切,像是委托人,又像代理人,通过“委托”来执行一些函数而不是直接调用它 ...

  2. xhEditor struts2实现图片上传

    xhEditor的环境搭建请参考http://blog.csdn.net/itmyhome1990/article/details/38422255,这时我们打开图片功能 是没有上传按钮的 如果想要出 ...

  3. 【ADO.Excel】ADO获取excel的Sheet集合

    using (OleDbConnection connection = new OleDbConnection(GetConnectionString())) { connection.Open(); ...

  4. 使用Reactive Extensions(Rx),对短时间内多次发生的事件限流

    使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 我之前有一篇文章介绍到了R ...

  5. Redis系统学习 四、超越数据结构

    5种数据结构组成了Redis的基础,其他没有关联特定数据结构的命令也有很多.我们已经看过一些这样的命令:info,select,flushdb,multi,exec,discard,watch,和ke ...

  6. 模块化与MVC

    [javascript激增的思考02]模块化与MVC 前言 之前我们遇到了这么一个项目,也就是我们昨天提到的,有很多的小窗口的,昨天说的太抽象了,今天我们再来理一理什么是小窗口(后面点说下),当时由于 ...

  7. 机器学习的Spark与Scala开发简介

     一.机器学习常用开发软件:Spark.Scala 1. Spark简介: MLlib包含的库文件有: 分类 降维 回归 聚类 推荐系统 自然语言处理 在线学习 统计学习方法:偏向理论性,数理统计的方 ...

  8. Servle中的会话管理

    最近整理了下会话管理的相关笔记,以下做个总结: 一.会话管理(HttpSession) 1.Web服务器跟踪客户状态的四种方法: 1).使用Servlet API的Session机制(常用) 2).使 ...

  9. Android中检测软键盘的弹出和关闭

    Android系统并没有提供明显的API来监听软键盘的弹出和关闭,但是在某些情况下我们还是有办法来检测软键盘的弹出和关闭. 从StackOverflow找到了一个不错的方法.但是这种只适用于在mani ...

  10. install cuda5 on ubuntu12.04

    1. sudo apt-get install libglapi-mesa 2. sudo apt-get install freeglut3-dev build-essential libx11-d ...