跟踪代码,发现session是可以得到,但是比如我打算枚举session的内容,缺没提供方法了。于是,我使用RTTI的盗窃法子,读取了私有变量
procedure RttiGetPrivateValue(AClass: TClass; AInstance: TObject; FieldName: string; var Value: TObject); var ref: TRttiContext; typ: TRttiType; mthd: TRttiMethod; fld: TRttiField; begin typ := ref.GetType(AClass); fld := typ.GetField(FieldName); //can get private value Value := fld.GetValue(AInstance).AsObject; end; procedure EnumSessionData(const Session: TDSSession); var SessionData: TDSSessionDictionaryData; MetaData: TDictionary可以看到,Session里面对于Tcp,默认的只有两个变量,; MetaObjects: TDictionary ; Key: string; begin RttiGetPrivateValue(TDSSession, Session, 'FSessionData', TObject(SessionData)); RttiGetPrivateValue(TDSSessionDictionaryData, SessionData, 'FMetaData', TObject(MetaData)); RttiGetPrivateValue(TDSSessionDictionaryData, SessionData, 'FMetaObjects', TObject(MetaObjects)); for Key in MetaData.Keys do log.Debug('Sesion[%s] = %s', [Key, MetaData[Key]]); for Key in MetaObjects.Keys do log.Debug('SesionObjects[%s] = %s', [Key, MetaObjects[Key].ClassName]); end; function TdmServer.DSServerTrace(TraceInfo: TDBXTraceInfo): CBRType; var Session: TDSSession; begin log.TrackMethod('TdmServer.DSServerTrace'); Session := TDSSessionManager.GetThreadSession; if Session.ObjectCreator <> nil then log.Debug(Session.ObjectCreator.ClassName); log.Debug(TraceInfo.Message); EnumSessionData(Session); //在这里试着枚举读取一下 Result := cbrUSEDEF; end;
Sesion[remoteip] = 192.168.101.11 Sesion[communicationprotocol] = tcp/ip 这里的remoteip就是调用者ip了,但是如果想到得到sessioin对应的tunnel的具体socket信息,缺是不能了。 这两个值是在 TDSTCPServerTransport.DoOnConnect里放入的,代码如下
procedure TDSTCPServerTransport.DoOnConnect(AContext: IIPContext); var IndyChannel: TDBXChannel; FilterChannel: TDBXFilterSocketChannel; Event: TDSTCPConnectEventObject; begin FilterChannel := TDBXFilterSocketChannel.Create(Filters); IndyChannel := CreateTcpChannel(AContext); {$IFNDEF POSIX} if CoInitFlags = -1 then CoInitializeEx(nil, COINIT_MULTITHREADED) else CoInitializeEx(nil, CoInitFlags); {$ENDIF} IndyChannel.Open; // set the delegate FilterChannel.Channel := IndyChannel; AContext.Data := FProtocolHandlerFactory.CreateProtocolHandler(FilterChannel); if AContext.Data is TDBXJSonServerProtocolHandler then begin if TDBXJSonServerProtocolHandler(AContext.Data).DSSession = nil then begin TDBXJSonServerProtocolHandler(AContext.Data).DSSession := TDSSessionManager.Instance.CreateSession留意一下key的大小写进去的是RmoteIp,出来却变成了remoteip了,所以默认的Session是不关系大小写的,这是因为TDictionary创建是并没指定TStringComparer.Ordinal。目前DataSnap还不支持自定义TDSSessionData的派生,因为TDSSession.CreateSessionData不是虚的。( function: TDSSession begin Result := TDSTCPSession.Create(AuthenticationManager); Result.PutData('CommunicationProtocol', 'tcp/ip'); //这里放了进去 Result.PutData('RemoteIP', AContext.Connection.Socket.Binding.PeerIP); //这里放了进去信息 end, '' ); end; end; if Assigned(FTDSTCPConnectEvent) and (AContext <> nil) and (AContext.Connection <> nil) and (FTcpServer <> nil) and FTcpServer.Active then begin if IndyChannel Is TDSTCPChannel then begin //enable keep alive, disable it, or leave the OS default setting as it is if FKeepAliveEnablement = kaEnabled then TDSTCPChannel(IndyChannel).EnableKeepAlive(FKeepAliveTime, FKeepAliveInterval) else if FKeepAliveEnablement = kaDisabled then TDSTCPChannel(IndyChannel).DisableKeepAlive; Event := TDSTCPConnectEventObject.Create(AContext.Connection.GetObject, TDSTCPChannel(IndyChannel)); end else Event := TDSTCPConnectEventObject.Create(AContext.Connection.GetObject, nil); try OnConnect(Event); except end; end; end;
没有评论:
发表评论