/// <summary> /// 获取单项配置 /// </summary> /// <param name="serverName"></param> /// <param name="commandName"></param> public static ServerConfigItem GetItem(string serverName, string commandName) { var key = ServerCommand.BuildCommandKey(serverName, commandName); ServerConfigItem item = null; items.TryGetValue(key, out item); return(item); }
/// <summary> /// 服务配置读取 /// </summary> /// <param name="serverName"></param> /// <param name="serverExpire"></param> /// <param name="nodes"></param> private static void LoadServerConfig(string serverName, int serverExpire, XmlNodeList nodes) { var commandName = string.Empty; var expires = 0; var mixedsplit = string.Empty; var version = string.Empty; var cacheDeleteAction = string.Empty; var objectName = string.Empty; foreach (XmlNode node in nodes) { commandName = XmlHelper.GetAttribute(node, "name", null); if (string.IsNullOrEmpty(commandName)) { continue; } if (Exists(serverName, commandName)) { throw new ConfigurationErrorsException(string.Format("Repeated Command Item {0}.{1} in {0}.config", serverName, commandName)); } var commandInfo = ServerCommand.GetCommand(serverName, commandName); if (commandInfo == null) { throw new ConfigurationErrorsException(string.Format("No Find Server Command {0}.{1} in {0}.config", serverName, commandName)); } var settingItem = new ServerConfigItem(); //cache expires settingItem.CacheExpires = int.TryParse(XmlHelper.GetAttribute(node, "expires", null), out expires) ? expires : serverExpire; //version version = XmlHelper.GetAttribute(node, "version"); if (!string.IsNullOrEmpty(version)) { if (GetVersionExpires(serverName, version) == 0) { throw new ConfigurationErrorsException(string.Format("Not Find Version:{2} config node, version info {0}.{1} version attribute in {0}.config", serverName, commandName, version)); } settingItem.CacheVersion = version; } settingItem.CacheKey = XmlHelper.GetAttribute(node, "key", null); if (string.IsNullOrEmpty(settingItem.CacheKey)) { settingItem.CacheKey = string.Concat(serverName, ".", commandName); } //deletes var deletes = node.SelectNodes("delete"); if (deletes.Count > 0) { settingItem.CacheDeletes = InitCacheDelete(commandInfo, deletes); } items.Add(ServerCommand.BuildCommandKey(serverName, commandName), settingItem); } }
/// <summary> /// 初始新实例 /// </summary> /// <param name="logManager"></param> /// <param name="port"></param> /// <exception cref="ArgumentNullException">logManager</exception> public ServerListen(LogManager logManager, int port) { //config if (port == 0) { this.Port = int.Parse(ConfigurationManager.AppSettings["Port"]); } else { this.Port = port; } this.Name = ConfigHelper.AppName; // if (string.IsNullOrEmpty(this.Name)) { throw new ApplicationException("Not Config AppName"); } // if (logManager == null) { throw new ArgumentNullException("logManager"); } // this.isDispose = false; this.StartTime = DateTime.Now; //init logManager.Message.WriteLine("Name:{0}", this.Name); logManager.Message.WriteLine("Port:{0}", this.Port); logManager.Message.WriteLine("Time:{0}", this.StartTime); this.logManager = logManager; this.connectionUnfinishedLogWriter = logManager.GetWriter("ConnectionUnfinished"); // this.serverLogger = new ServerLogger(logManager); ServerCache.Init(logManager); //init context ServerCommand.Init(logManager); ServerConfig.Init(logManager, ServerCommand.Servers); //socket this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.Socket.Bind(new IPEndPoint(IPAddress.Any, this.Port)); //为了性能保证,服务暂不做连接数限制 this.Socket.Listen(LISTEN_BACKLOG); this.Socket.BeginAccept(this.AcceptCallback, this.Socket); }
/// <summary> /// new command /// </summary> /// <param name="parameterLength"></param> /// <param name="socket"></param> private void NewCommand(Socket socket, int parameterLength) { object value = null; byte[] valueBuffer = null; var serverName = string.Empty; var commandName = string.Empty; var result = CsResult.Fail; var begin = DateTime.MaxValue; var end = DateTime.MaxValue; double invokeSeconds = 0; var start = DateTime.Now; var cacheType = ServerCacheType.NoCache; //exec serverName = (string)this.Receive(socket, STRING_TYPE, true); commandName = (string)this.Receive(socket, STRING_TYPE, true); var commandInfo = ServerCommand.GetCommand(serverName, commandName); if (commandInfo == null) { value = string.Format("Not Find Command:{0}.{1}", serverName, commandName); } // throw new NotFindCommandException(nameSpace, commandName); else if (commandInfo.Parameters.Length != parameterLength) { value = string.Format("{0}.{1} Parameter Legnth <> Invoke Parameter Length", serverName, commandName); } //throw new ApplicationException(string.Format("{0}.{1} Parameter Legnth <> Invoke Parameter Length", nameSpace, commandName)); object[] parameters = null; //no error if (value == null) { //get parameter if (parameterLength > 0) { parameters = new object[parameterLength]; for (var i = 0; i < parameterLength; i++) { if (commandInfo.Parameters[i].IsOut) { this.Receive(socket, commandInfo.Parameters[i].ParameterType, false); } else { parameters[i] = this.Receive(socket, commandInfo.Parameters[i].ParameterType, true); if (ReceiveParameterError.ERROR.Equals(parameters[i])) { value = "Parameter Error"; } } } } // if (value != null) { //parameter error result = CsResult.Fail; } else { //commandStopwatch.Start(); var invokeStart = DateTime.Now; try { result = this.Invoke(commandInfo, parameters, out valueBuffer, out cacheType); } catch (TargetInvocationException exception) { result = CsResult.Fail; this.serverLogger.CommandException(serverName, commandName, exception); value = exception.GetBaseException().Message; } catch (Exception exception) { result = CsResult.Fail; this.serverLogger.CommandException(serverName, commandName, exception); value = exception.Message; } //commandStopwatch.Stop(); invokeSeconds = DateTime.Now.Subtract(invokeStart).TotalSeconds; } } else { //read parameters data if (parameterLength > 0) { for (var i = 0; i < parameterLength; i++) { //length var length = BitConverter.ToInt32(SocketHelper.Receive(socket, CsSocket.LENGTH_BUFFER_SIZE), 0); //body using (var m = SocketHelper.Receive(socket, length, CsSocket.BODY_BUFFER_SIZE)) { m.Close(); } } } } //send using (var stream = new MemoryStream(CsSocket.BODY_BUFFER_SIZE)) { //send length stream.Write(BitConverter.GetBytes((int)result), 0, CsSocket.LENGTH_BUFFER_SIZE); //send out parameter length if (result == CsResult.Success) { stream.Write(valueBuffer, 0, valueBuffer.Length); } else { //error output using (var m = new MemoryStream(CsSocket.BODY_BUFFER_SIZE)) { CsSerializer.Serialize(m, value); stream.Write(BitConverter.GetBytes((int)m.Length), 0, CsSocket.LENGTH_BUFFER_SIZE); m.WriteTo(stream); } } socket.Send(stream.GetBuffer(), 0, (int)stream.Length, SocketFlags.None); } this.serverLogger.Command(this, serverName, commandName, result == CsResult.Success, cacheType, invokeSeconds, DateTime.Now.Subtract(start).TotalSeconds); }
/// <summary> /// 是否具有指定项 /// </summary> /// <param name="serverName"></param> /// <param name="commandName"></param> private static bool Exists(string serverName, string commandName) { return(items.ContainsKey(ServerCommand.BuildCommandKey(serverName, commandName))); }
private void NewCommandInvoke(Socket socket, byte parameterLength, string serverName, string commandName, int commandStart) { object value = null; object[] parameters = null; var commandInfo = ServerCommand.GetCommand(serverName, commandName); if (commandInfo == null) { value = string.Format("Not Find Command:{0}.{1}", serverName, commandName); } else if (commandInfo.Parameters.Length != parameterLength) { value = string.Format("{0}.{1} Client Command Parameters And Server Parameters No Match", serverName, commandName); } else { //get parameter if (parameterLength > 0) { parameters = new object[parameterLength]; for (var i = 0; i < parameterLength; i++) { if (commandInfo.Parameters[i].IsOut) { CsSocket.Receive(socket); } else { parameters[i] = CsSocket.Receive(socket, commandInfo.Parameters[i].ParameterType); } } } } //cache byte[] cacheBuffer = null; String cacheVersion = null, cacheKey = null; var cacheType = ServerCacheType.NoCache; ServerConfigItem configItem = null; bool cacheEnable = false; //no error & get cache if (value == null) { if (ServerCache.Enable) { configItem = ServerConfig.GetItem(commandInfo.Server, commandInfo.Name); cacheEnable = configItem != null && configItem.CacheExpires > 0; } //cache get if (cacheEnable) { //mode = version if (configItem.CacheVersion != null) { try { cacheVersion = ServerCache.Cache.Get(configItem.CacheVersion); if (cacheVersion != null && cacheVersion != "") { //get cache cacheKey = ServerCache.BuildKey(configItem.CacheKey, cacheVersion, parameters); //value = ServerCache.Cache.Get(cacheKey, commandInfo.Method.ReturnType); cacheBuffer = ServerCache.Cache.Get <byte[]>(cacheKey); cacheType = cacheBuffer != null ? ServerCacheType.Cached : ServerCacheType.NoCache; } else { //no version , set no cache cacheEnable = false; } } catch (Exception e) { this.logManager.Exception(e); } } else { //get cache cacheKey = ServerCache.BuildKey(configItem.CacheKey, null, parameters); try { //value = ServerCache.Cache.Get(cacheKey, commandInfo.Method.ReturnType); cacheBuffer = ServerCache.Cache.Get <byte[]>(cacheKey); cacheType = cacheBuffer != null ? ServerCacheType.Cached : ServerCacheType.NoCache; } catch (Exception e) { this.logManager.Exception(e); } } } } var result = false; //cached if (cacheType == ServerCacheType.Cached) { socket.Send(cacheBuffer); result = true; } //no error ,invoke else if (value == null) { //var invokeStart = DateTime.Now; try { value = commandInfo.Method.Invoke(commandInfo.Instance, parameters); result = true; } catch (TargetInvocationException exception) { result = false; this.logManager.Exception(exception.GetBaseException()); value = exception.GetBaseException().Message; } catch (Exception exception) { result = false; this.logManager.Exception(exception); value = exception.Message; } //invokeSeconds = DateTime.Now.Subtract(invokeStart).TotalSeconds; //build value Buffer if (result) { using (var m = new MemoryStream()) { //write result m.WriteByte((byte)CsResult.Success); //send out parameter length //buffer parameter length , parameter index + parameter length + parameter body + bodylength + body //parameter count writer m.WriteByte(commandInfo.OutsIndexLength); //parameter write if (commandInfo.OutsIndexLength > 0) { for (byte i = 0, l = commandInfo.OutsIndexLength; i < l; i++) { //write index m.WriteByte(commandInfo.OutsIndex[i]); //write parameter CsSocket.WriteDataItem(m, parameters[commandInfo.OutsIndex[i]]); } } //body CsSocket.WriteDataItem(m, value); //build value buffer completed //svae value buffer to cache //if (result == CsResult.Success && cacheType == CacheType.NoCache && hasContent && commandInfo.CacheExpires > 0) if (cacheEnable && cacheType == ServerCacheType.NoCache) { cacheBuffer = m.ToArray(); try { //set cache ServerCache.Cache.Set(cacheKey, cacheBuffer, configItem.CacheExpires); cacheType = ServerCacheType.NewCache; } catch (Exception e) { this.logManager.Exception(e); } } //delete cache if (ServerCache.Enable && cacheEnable && configItem.CacheDeletes != null) { this.DeleteCache(commandInfo, configItem, parameters); } //send value if (cacheType == ServerCacheType.NewCache) { socket.Send(cacheBuffer); } else { socket.Send(m.GetBuffer(), 0, (int)m.Length, SocketFlags.None); } } } } else { //parameter error result = false; //value = "parameter error"; } //send error if (result == false) { using (var m = new MemoryStream()) { m.WriteByte((byte)CsResult.Fail); //write failure message CsSocket.WriteDataItem(m, (string)value); // socket.Send(m.GetBuffer(), 0, (int)m.Length, SocketFlags.None); } } // if (this.logMessage.Enable) { //this.logMessage.WriteTimeLine("{0}: {1}.{2}:{3}, Cache:{4}, InvokeSeconds:{5},Seconds:{6}", // this.id, serverName, commandName, result ? "Success" : "Failure", cacheType, invokeSeconds, DateTime.Now.Subtract(start).TotalSeconds); //stopwatch.Stop(); //var elapsedMilliseconds = stopwatch.ElapsedMilliseconds; var elapsedMilliseconds = Environment.TickCount - commandStart; //this.logMessage.WriteTimeLine("{0}: {1}.{2}:{3}, Cache:{4}, Elapsed:{5}", // this.id, serverName, commandName, result ? "Success" : "Failure", cacheType, stopwatch.Elapsed.TotalSeconds); this.logMessage.WriteTimeLine("{0}\t{1}\t{2}.{3}\t{4}\t{5}", this.id , cacheType , serverName , commandName , elapsedMilliseconds , (result ? "OK" : (string)value)); } }