移动平台下的Socket几个问题

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

在页游时代,使用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不致,也认为是需要重登录游戏了,因为无论你拿什么密钥串都将无法再登录游戏,服务器认为这个请求是非法的;

 

技术改变世界! --狂诗绝剑
目录
相关文章
|
网络协议 Unix API
iOS - Socket 网络套接字
1、Socket 套接字 所谓 Socket,通常称为 “套接字”,网络应用程序通过套接字向网络发送请求或者应答网络请求。Socket 通常用于描述 IP 地址和端口,是应⽤层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,是一个通信链的句柄,可以用来实现不同虚拟机或者不同计算机之间的通信。
1978 0
|
4月前
|
网络协议
关于套接字socket的网络通信。&聊天系统 聊天软件
关于套接字socket的网络通信。&聊天系统 聊天软件
|
5月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
166 0
|
编解码 开发工具 Android开发
如何在Android端实现轻量级RTSP服务(类似于IPC)
首先声明一点,本blog提到的轻量级RTSP服务,类似于网络摄像头(IPC),而非传统意义的接受外部推流的RTSP服务器。
681 0
|
网络协议 C语言 iOS开发
iOS 使用Socket
Socket 套接字 纯C语言的,跨平台的 HTTP协议是基于Socket的 基本操作: 导入头文件 创建Socket 连接到服务器 发送数据给服务器 从服务器接收数据 关闭连接 服务开启 打开本机模拟服务器端...
725 0