管理靠一单例TDSSessionManager来管理。对于目前说到TDSTCPServerTransport,建立的的Session为TDSTCPSession,它是TDSSession的子类。
Session在开始连接后,就创建了,再连接断开后消亡。
TDSSession = class private FStartDateTime: TDateTime; /// creation timestamp FDuration: Integer; /// in miliseconds, 0 for infinite (default) FStatus: TDSSessionStatus; /// default idle FLastActivity: Cardinal; /// timestamp of the last activity on this session FUserName: String; /// user name that was authenticated with this session FSessionName: String; /// session name, may be internally generated, exposed to 3rd party FMetaData: TDictionary可以看出,Session可以用存储了很多东西 。用得多的是FMetaData与FMetaObjects; /// map of metadata stored in the session FMetaObjects: TDictionary ; /// map of objects stored in the session FUserRoles: TStrings; /// user roles defined through authentication FCache: TDSSessionCache; FLastResultStream: TObject; /// Allow any object which owns a stream, or the stream itself, to be stored here FCreator: TObject; /// Creator of the session object reference
对于字符串,PutData放进去,GetData取出来;对于Object,PutObject放进去,GetObject取出来。
使用方法为
TDSSessionManager.GetThreadSession.PutData('userid', userId); userId := TDSSessionManager.GetThreadSession.GetData('userid');另外,放入FMetaObjects的Object,Session的Free时,会自动帮忙Free,所以不必自己去Free的。
关于Session的超时,
这里自然就想到了TDSTCPServerTransport的KeepAliveInterval和KeepAliveTime属性,这两个属性,其实和Session管理没关系。
跟踪代码,这两个属性的反应在IdStackWindows.pas的
procedure TIdStackWindows.SetKeepAliveValues(ASocket: TIdStackSocketHandle; const AEnabled: Boolean; const ATimeMS, AInterval: Integer); var ka: tcp_keepalive; Bytes: DWORD; begin // SIO_KEEPALIVE_VALS is supported on Win2K+ only if AEnabled and (Win32MajorVersion >= 5) then begin ka.onoff := 1; ka.keepalivetime := ATimeMS; ka.keepaliveinterval := AInterval; WSAIoctl(ASocket, SIO_KEEPALIVE_VALS, @ka, SizeOf(ka), nil, 0, @Bytes, nil, nil); end else begin SetSocketOption(ASocket, Id_SOL_SOCKET, Id_SO_KEEPALIVE, iif(AEnabled, 1, 0)); end; end;里,其实就是简单设置了一下socket fd的属性,所以说TDSSessionManager毛关系都没有。
另外, KeepAliveTime默认值为300000,也就是300秒,KeepAliveInterval默认值为100,这是啥意思呢。KeepAliveTime是sockfd最后一次通讯后,等待了的时间,如果300秒内没通讯,socket栈就自己开始发送心跳探测了,如果每次都没回答,就每隔KeepAliveInterval毫秒问一次。至于问多少次认为是网络断开了,根据Windows OS来定的,windows 2000, 2003是5次,vista以后问10次。也就是说,根据TDSTCPServerTransport的默认设定,网络断了,在win7上,要300+0.1*10,也即是301秒才知道网络断了。
OS的系统设定更长,没数据通讯后2小时才开始探测,每隔1秒探测一回。
SIO_KEEPALIVE_VALS值Windows的OS独有的,Unix还是用SO_KEEPALIVE。
跑题远了,回到正题。如何监控Session呢,TDSSessionManager提供了方法给你插入监听事件。
上代码
var event: TDSSessionEvent; initialization event := procedure(Sender: TObject; const EventType: TDSSessionEventType; const Session: TDSSession) begin case EventType of SessionCreate: begin LogInfo('SessionCreate'); LogInfo(Format('SessionName=%s', [Session.SessionName])); end; SessionClose: begin LogInfo('SessionClose'); LogInfo(Format('SessionName=%s', [Session.SessionName])); end; end; end; TDSSessionManager.Instance.AddSessionEvent(event); finalization TDSSessionManager.Instance.RemoveSessionEvent(event);这样就可以了,有多少事件都可以插入监听。
没有评论:
发表评论