using System; using System.Collections.Generic; using CommonServer.Server; using CommonLang.Protocol; using System.Collections.Specialized; using SuperSocket.SocketBase; using SuperSocket.SocketBase.Protocol; using SuperSocket.SocketBase.Config; using System.Reflection; using CommonLang; using CommonLang.Log; using CommonLang.Net; using System.IO; using CommonLang.ByteOrder; namespace CommonServer.SSocket.SuperSocket { public class SocketAcceptor : IServer { private static Logger log = LoggerFactory.GetLogger("SSocket"); private readonly INetPackageCodec _codec; private readonly IReceiveFilterFactory _filter; private readonly EmulateLagging _emu_lagging; private AppServerImpl _server; private string _connect_string; private ArraySegment _zero_segment = new ArraySegment(new byte[0]); internal long mTotalSentBytes; internal long mTotalRecvBytes; public string ClientConnectString { get { return _connect_string; } } public INetPackageCodec PackageCodec { get { return _codec; } } public long TotalSentBytes { get { return mTotalSentBytes; } } public long TotalRecvBytes { get { return mTotalRecvBytes; } } public int SessionCount { get { return _server.SessionCount; } } public bool EmulateLag { get { return _emu_lagging.EmulateLag; } } //------------------------------------------------------------------------------------------------------------------------- public SocketAcceptor(INetPackageCodec codec, IReceiveFilterFactory filter) { this._codec = codec; this._filter = filter; this._emu_lagging = new EmulateLagging(); } public void Open(string host, int port, IServerListener listener) { CommonLang.Properties game_server_cfg = new CommonLang.Properties(); game_server_cfg["SuperSocket.HOST"] = host; game_server_cfg["SuperSocket.PORT"] = port.ToString(); game_server_cfg["SuperSocket.CLIENT_CONNECT_STRING"] = host + ":" + port; this.Open(game_server_cfg, listener); } /// ///
        /// SuperSocket.HOST = 192.168.1.1
        /// SuperSocket.PORT = 9527
        /// SuperSocket.CLIENT_CONNECT_STRING = 192.168.1.1:9527
        /// 
///
/// /// public void Open(IDictionary config, IServerListener listener) { string host = config["SuperSocket.HOST"]; string port = config["SuperSocket.PORT"]; if (host == null || port == null) { throw new Exception(@"Config Must Be Contains 'SuperSocket.HOST' and 'SuperSocket.PORT' fields !"); } int dport = 0; if (!int.TryParse(port, out dport)) { throw new Exception(@"Config 'SuperSocket.PORT' must be a digit value !"); } this._connect_string = config["SuperSocket.CLIENT_CONNECT_STRING"]; if (_connect_string == null) { throw new Exception(@"Config Must Be Contains 'SuperSocket.CLIENT_CONNECT_STRING' fields !"); } ServerConfig cfg = new ServerConfig(); cfg.SyncSend = false; cfg.Port = dport; cfg.Mode = SocketMode.Tcp; cfg.DisableSessionSnapshot = true; cfg.LogCommand = false; cfg.Name = "Server"; cfg.ClearIdleSession = true; cfg.ClearIdleSessionInterval = 10; cfg.IdleSessionTimeOut = 10000; cfg.LogBasicSessionActivity = false; cfg.SendingQueueSize = 1000; cfg.SendTimeOut = 5000; cfg.TextEncoding = "UTF-8"; cfg.MaxConnectionNumber = 1000; cfg.MaxRequestLength = 1024 * 100; foreach (string key in config.Keys) { try { if (key.StartsWith("SuperSocket.")) { string value = config[key]; string fname = key.Substring("SuperSocket.".Length); FieldInfo finfo = typeof(ServerConfig).GetField(fname); if (finfo != null) { finfo.SetValue(cfg, Parser.StringToObject(value.Trim(), finfo.FieldType)); log.Info(string.Format(" {0} = {1}", key, value)); } } } catch (Exception err) { } } this.Open(cfg, listener); } /// ///
        /// cfg.name: 服务器实例的名称;
        /// cfg.serverType: 服务器实例的类型的完整名称;
        /// cfg.serverTypeName: 所选用的服务器类型在 serverTypes 节点的名字,配置节点 serverTypes 用于定义所有可用的服务器类型,我们将在后面再做详细介绍;
        /// cfg.ip: 服务器监听的ip地址。你可以设置具体的地址,也可以设置为下面的值 Any - 所有的IPv4地址 IPv6Any - 所有的IPv6地址
        /// cfg.port: 服务器监听的端口;
        /// cfg.listenBacklog: 监听队列的大小;
        /// cfg.mode: Socket服务器运行的模式, Tcp (默认) 或者 Udp;
        /// cfg.disabled: 服务器实例是否禁用了;
        /// cfg.startupOrder: 服务器实例启动顺序, bootstrap 将按照此值的顺序来启动多个服务器实例;
        /// cfg.sendTimeOut: 发送数据超时时间;
        /// cfg.sendingQueueSize: 发送队列最大长度, 默认值为5;
        /// cfg.maxConnectionNumber: 可允许连接的最大连接数;
        /// cfg.receiveBufferSize: 接收缓冲区大小;
        /// cfg.sendBufferSize: 发送缓冲区大小;
        /// cfg.syncSend: 是否启用同步发送模式, 默认值: false;
        /// cfg.logCommand: 是否记录命令执行的记录;
        /// cfg.logBasicSessionActivity: 是否记录session的基本活动,如连接和断开;
        /// cfg.clearIdleSession: true 或 false, 是否定时清空空闲会话,默认值是 false;
        /// cfg.clearIdleSessionInterval: 清空空闲会话的时间间隔, 默认值是120, 单位为秒;
        /// cfg.idleSessionTimeOut: 会话空闲超时时间; 当此会话空闲时间超过此值,同时clearIdleSession被配置成true时,此会话将会被关闭; 默认值为300,单位为秒;
        /// cfg.security: Empty, Tls, Ssl3. Socket服务器所采用的传输层加密协议,默认值为空;
        /// cfg.maxRequestLength: 最大允许的请求长度,默认值为1024;
        /// cfg.textEncoding: 文本的默认编码,默认值是 ASCII;
        /// cfg.defaultCulture: 此服务器实例的默认 thread culture, 只在.Net 4.5中可用而且在隔离级别为 'None' 时无效;
        /// cfg.disableSessionSnapshot: 是否禁用会话快照, 默认值为 false.
        /// cfg.sessionSnapshotInterval: 会话快照时间间隔, 默认值是 5, 单位为秒;
        /// cfg.keepAliveTime: 网络连接正常情况下的keep alive数据的发送间隔, 默认值为 600, 单位为秒;
        /// cfg.keepAliveInterval: Keep alive失败之后, keep alive探测包的发送间隔,默认值为 60, 单位为秒;
        /// 
///
/// /// public void Open(ServerConfig cfg, IServerListener listener) { this._server = new AppServerImpl(listener, this, _filter); if (_server.Setup(cfg)) { this._emu_lagging.Start(); this._server.Start(); } else { throw new Exception("Open Server Failed !"); } } public void Dispose() { _emu_lagging.Dispose(); _server.Stop(); _server.Dispose(); } //------------------------------------------------------------------------------------------------------------------------- public void Broadcast(IMessage message) { foreach (ISession session in _server.GetAllSessions()) { session.Send(message); } } public bool HasSession(ISession session) { return _server.GetSessionByID(session.ID) != null; } public ISession GetSessionByID(string sessionID) { return _server.GetSessionByID(sessionID) as ISession; } public IEnumerable GetSessions() { return _server.GetAllSessions(); } //------------------------------------------------------------------------------------------------------------------------- internal void SendDelay(Session session, byte[] buff, int offset, int length) { _emu_lagging.SendDelay(session, buff, offset, length); } public void SetEmulateLaggingMS(int min, int max) { _emu_lagging.SetEmulateLaggingMS(min, max); } public void GetEmulateLaggingMS(out int min, out int max) { _emu_lagging.GetEmulateLaggingMS(out min, out max); } //------------------------------------------------------------------------------------------------------------------------- protected internal virtual bool DoDecodeInternal(Session session, BinaryRequestInfo bin, out int bytes, out object message) { bytes = bin.Body.Length + 4; using (var ms = new MemoryStream(bin.Body)) { object obj; if (_codec.doDecode(ms, out obj)) { message = obj; return true; } } message = null; return false; } protected internal virtual bool DoEncodeInternal(Session session, object message, out ArraySegment bytes) { using (var ms = new MemoryStream(ServerFactory.SEND_BUFF_SIZE)) { LittleEdian.PutS32(ms, 0); if (_codec.doEncode(ms, message)) { int length = (int)ms.Position; int blen = length - 4; if (blen < 0) { throw new Exception(string.Format("sending trunk size={0} type={1}", blen, message.GetType().FullName)); } ms.Position = 0; LittleEdian.PutS32(ms, blen); bytes = new ArraySegment(ms.GetBuffer(), 0, length); return true; } } bytes = _zero_segment; return false; } //------------------------------------------------------------------------------------------------------------------------- class AppServerImpl : AppServer { internal readonly SocketAcceptor _owner; internal readonly IServerListener _listener; public AppServerImpl(IServerListener listener, SocketAcceptor owner, IReceiveFilterFactory filter) : base(filter) { this._owner = owner; this._listener = listener; this.NewRequestReceived += AppServerImpl_NewRequestReceived; } private void AppServerImpl_NewRequestReceived(Session session, BinaryRequestInfo requestInfo) { int bytes; object msg; if (_owner.DoDecodeInternal(session, requestInfo, out bytes, out msg)) { _owner.mTotalRecvBytes += bytes; session.NewRequestReceived(bytes, msg); } } protected override bool RegisterSession(string sessionID, Session appSession) { if (base.RegisterSession(sessionID, appSession)) { appSession.NewSessionConnected(_owner, _listener.OnSessionConnected(appSession), _owner.PackageCodec); return true; } return false; } protected override void OnNewSessionConnected(Session session) { base.OnNewSessionConnected(session); } protected override void OnStarted() { base.OnStarted(); _listener.OnInit(_owner); } protected override void OnStopped() { base.OnStopped(); _listener.OnDestory(); } } } }