【DIOCP3-说明书】关于服务端的KeepAlive属性(心跳)

DIOCP3中服务端(IocpTcpServer)中提供一个KeepAlive属性,之前版本默认开启,2014-12-30之后的版本默认是关闭的。

首先要搞明白KeepAlive的作用是什么,服务端开启KeepAlive后在建立连接的时候会设置Socket的SO_KeepAlive选项

 

MSDN的解释是这样的:

http://msdn.microsoft.com/en-us/library/windows/desktop/ee470551(v=vs.85).aspx

SO_KEEPALIVE socket option

The SO_KEEPALIVE socket option is designed to allow an application to enable keep-alive packets for a socket connection.

SO_KEEPALIVE 套接字选项是被设计允许应用程序对一个套接字连接开启keep-alive包(翻得不好,意思基本上对了)

 

开启后,如果客户端关闭(或者网络异常)等情况,服务端就会马上知道。这样服务端就会断开该连接。但是该选项并不是所有的环境下面都能运作的很好,据我所知,如果客户端是Andriod,就不行,还有一些硬件设备,也是不行的,所以我改成默认是关闭状态。

关闭后,问题就来了,客户端如果断线,可能服务器端就无法及时发现,这样服务端会出现很多死链接。只有当进行对socket进行操作(比如发送数据socket.send)时遇到异常时才会发现该连接无效,然后进行断开。

一般实际应用,如果要保持长连接,可以在客户端发送心跳数据包(这个数据包因为要根据自己定义的协议格式进行发送,所以无法在底层完成。)然后在服务端做超时检测,如果超过一定的时间(这个时间自己协定)就把该连接主动T掉。

【DIOCP3-说明书】关于DIOCP3服务端常见的问题

这几天群里面使用DIOCP3的人越来越多,一般或多或少都会碰到一些问题,碰到问题并不可怕,可怕的是不知道如果下手去查找问题,解决问题。服务端的编写都一样,需要小心谨慎,毕竟我们要写的程序是需要长期运行的,不能有半点马虎。每一行代码都要认真对待,我现在把大家碰到的问题整理下,希望大家碰到问题时,好好检查下代码,看看是不是也有类似的问题。

 

第一,也是很多人容易犯的错误,不要在diocp3事件中,直接访问UI

    这个情况几乎我每次都强调,但基本上90%的人都犯这样的错误,因为diocp3中,所有的事件都在线程中触发的,UI资源一般都不是线程安全的,直接访问UI,一般会锁死线程,程序退出时无法退出进程,而且会出现不可预料的错误。
   日志记录方面如果要显示到Memo中,请使用线程日志安全类SafeLogger,可以参考safelogger的demo,虽然Memo是做的SendMessage处理,还是不建议直接在线程池对Memo直接进行操作

 

第二,访问违规错误。

    首先跟踪下代码看看,访问违规的错误代码是哪一行引起的,看看对象是否提前是否,或者是公用的对象,如果是公用的对象是否有做临界处理。如果异常停留在diocp底层的代码,多数情况下面是程序栈帧被破坏,检查下指针操作的位置(move,copyMemory的位置)看看目标指针是否有越界和指定错误的情况。建议应用层,少用指针和结构体,用操作对象或者内存流来代替结构体和指针操作。

 

第三,日志的问题。

    diocp底层记录日志在Debug模式下面记录日志比较详细,每个连接的断开<包括主动和对方断开>都做了日志记录。那些日志一般都是正常存在的。

 

第四,心跳和重连。

    diocp3中有设置KeepAlive的选项,但是这个选项不是万能的,有很多客户端突然断线,或者某些机器上面会不起作用。这个时候需要做业务层的心跳包,一般处理方法是,客户端定时发送很小的数据包,到服务端,服务端做轮询的超时检测,把超时的连接主动在服务端T掉,客户端在发送数据包的过程中也可以触发没有正常连接的异常,然后进行重连。

 

最后再强调下,服务端编程,要处理要多线程资源访问的问题,注意好指针操作。要写出稳健的服务端,还需要逻辑代码和diocp3的配合,需要谨慎对待。