在页游时代,使用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. 【hanoi】hanoi移动次数和移动步骤

    #include<stdio.h> #include<stdlib.h> //移动次数 int hanoi(int num) { ; ) { ; } else { all = ...

  2. What's New in Core Data in iOS 7

    What's New in Core Data in iOS 7 该文档主要描述coredata 在ios7的新功能特性. Core Data and iCloud 我们添加改进了对Core Data ...

  3. HTML5 拖拽效果实现

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  4. python 爬虫总结【转】

    1.基本抓取网页 get方法 import urllib2 url = "http://www.baidu.com" response = urllib2.urlopen(url) ...

  5. mysql 和 mongo db 语法对比

    本文描述了MySQL中的常用SQL语句在MongoDB中的写法,如果你长期使用MySQL而对MongoDB跃跃欲试,这篇简单的文章可以帮助你更快的进入角色.查询:MySQL:SELECT * FROM ...

  6. 自用类库整理之SqlHelper和MySqlHelper

    自用类库整理之SqlHelper和MySqlHelper 自用的SQLHelper和MySqlHelper,除一些通用方法外,封装了一些很实用的批量操作方法,简单介绍下 SqlHelper Execu ...

  7. 七个开法者经常忽略或误用的JavaScript基本知识

    七个开法者经常忽略或误用的JavaScript基本知识 翻译自 http://tech.pro/tutorial/1453/7-javascript-basics-many-developers-ar ...

  8. 绘制基本图形和线型(StrokeStyle)的设置详解

    绘制基本图形和线型(StrokeStyle)的设置详解 目前,在博客园上,相对写得比较好的两个关于Direct2D的教程系列,分别是万一的Direct2D系列和zdd的Direct2D系列.有兴趣的网 ...

  9. JS关闭当前页面的方法

    JS关闭当前页面的方法 一.不带任何提示关闭窗口的js代码 1 <a href="javascript:window.opener=null;window.open('','_self ...

  10. C#代码和javascript函数相互调用

    C#代码与javaScript函数的相互调用 问:1.如何在JavaScript访问C#函数?2.如何在JavaScript访问C#变量?3.如何在C#中访问JavaScript的已有变量?4.如何在 ...