public ClientSocketProcessor(SocketAsyncEventArgPool connectPool, SocketAsyncEventArgPool recSendPool, int maxRecSendConnection, int bufferSize, int numberMessageOfPerConnection, int prefixHandleLength, bool supportKeepAlive = false, string specialName = "") { this.poolOfConnectEventArgs = connectPool; this.poolOfRecSendEventArgs = recSendPool; this.specialNameForSimplePerf = specialName; this.simplePerf = new SimplePerformanceCounter(true, false, specialName); this.maxConnectionCount = maxRecSendConnection; this.maxConcurrentConnection = new Semaphore(maxRecSendConnection, maxRecSendConnection); this.bufferSize = bufferSize; this.numberMessagesOfPerConnection = numberMessageOfPerConnection; this.prefixHandleLength = prefixHandleLength; this.supportKeepAlive = supportKeepAlive; if (this.supportKeepAlive) { dictPoolOfHeartBeatRecSendEventArgs = new Dictionary <string, SocketAsyncEventArgPool>(); thHeartBeat = new Thread(new ThreadStart(RunHeartBeat)); thHeartBeat.IsBackground = true; thHeartBeat.Start(); } }
private bool ReuseHeartBeatSAEA(List <Message> messages, string serverEndPointKey) { try { if (!dictPoolOfHeartBeatRecSendEventArgs.ContainsKey(serverEndPointKey)) { return(false); } SocketAsyncEventArgPool thisPortSocketPool = dictPoolOfHeartBeatRecSendEventArgs[serverEndPointKey]; //while (!thisPortSocketPool.IsEmpty) while (true) { cleanSignal.Reset(); //鉴于IsEmpty有问题,确保有Pop尝试! SocketAsyncEventArgs arg = thisPortSocketPool.Pop(); if (arg == null) { if (thisPortSocketPool.IsEmpty) { LogManager.LogTraceInfo(string.Format("poolKey:{0} 's pool empty now with count:{1}", serverEndPointKey, thisPortSocketPool.Count)); return(false); } else { Thread.Sleep(1); continue; } } GetSimplePerf().PerfClientReuseConnectionCounter.Increment(); GetSimplePerf().PerfClientIdleConnectionCounter.Decrement(); ClientUserToken userToken = (ClientUserToken)arg.UserToken; userToken.CreateNewSendDataHolder(); SendDataHolder sendDataHodler = userToken.sendDataHolder; sendDataHodler.SetSendMessage(messages); MessagePreparer.GetDataToSend(arg); sendDataHodler.ArrayOfMessageToSend[0].StartTime = DateTime.Now; StartSend(arg); return(true); } } catch (Exception pickErr) { LogManager.Log(string.Format("pick socket from poolKey:{0} occur error!", serverEndPointKey), pickErr); } finally { cleanSignal.Set(); } return(false); }
public void Stop() { try { listenSocket.Close(); listenSocket = null; bufferManager = null; poolOfAcceptEventArgs = null; poolOfRecSendEventArgs = null; } catch { } }
public SocketListener(Func <byte[], byte[]> dataProcessor) { this.dataProcessor = dataProcessor; ServerSetting setting = ReadConfigFile.GetServerSetting(); this.receivePrefixLength = setting.receivePrefixLength; this.bufferSize = setting.bufferSize; this.supportKeepAlive = setting.useKeepAlive; this.bufferManager = new BufferManager(setting.bufferSize * setting.numberOfSaeaForRecSend * setting.opsToPreAllocate, setting.bufferSize * setting.opsToPreAllocate); this.poolOfAcceptEventArgs = new SocketAsyncEventArgPool(); this.poolOfRecSendEventArgs = new SocketAsyncEventArgPool(); this.maxConcurrentConnection = new Semaphore(setting.numberOfSaeaForRecSend, setting.numberOfSaeaForRecSend); Init(setting); StartListen(setting); }
private void SetToHeartBeatStatus(SocketAsyncEventArgs e, ClientUserToken userToken) { //加入support keepalive机制处理逻辑 userToken.startTime = DateTime.Now; if (!userToken.isReuseConnection) { userToken.isReuseConnection = true; } else { GetSimplePerf().PerfClientReuseConnectionCounter.Decrement(); } GetSimplePerf().PerfClientIdleConnectionCounter.Increment(); if (!dictPoolOfHeartBeatRecSendEventArgs.ContainsKey(userToken.ServerEndPointKey)) { lock (this) { if (!dictPoolOfHeartBeatRecSendEventArgs.ContainsKey(userToken.ServerEndPointKey)) { SocketAsyncEventArgPool pool = new SocketAsyncEventArgPool(); pool.Push(e); dictPoolOfHeartBeatRecSendEventArgs.Add(userToken.ServerEndPointKey, pool); } else { dictPoolOfHeartBeatRecSendEventArgs[userToken.ServerEndPointKey].Push(e); } } } else { dictPoolOfHeartBeatRecSendEventArgs[userToken.ServerEndPointKey].Push(e); } }
private void RunHeartBeat() { int waitTime = 180000; bool alreadyChecked = false; while (true) { if (alreadyChecked) { if (!DateTime.Now.Hour.Equals(3)) { alreadyChecked = false; } Thread.Sleep(waitTime); } if (DateTime.Now.Equals(3)) { foreach (string poolKey in dictPoolOfHeartBeatRecSendEventArgs.Keys) { SocketAsyncEventArgPool thisPortKey = dictPoolOfHeartBeatRecSendEventArgs[poolKey]; if (thisPortKey.IsEmpty) { continue; } Stopwatch sw = new Stopwatch(); sw.Start(); bool existNeedReuseItem = false; cleanSignal.WaitOne(); SocketAsyncEventArgs heartBeatSAEA = thisPortKey.Pop(); List <SocketAsyncEventArgs> listRepush = new List <SocketAsyncEventArgs>(); while (!thisPortKey.IsEmpty) { if (heartBeatSAEA != null) { ClientUserToken userToken = (ClientUserToken)heartBeatSAEA.UserToken; if (DateTime.Now.Subtract(userToken.startTime).TotalSeconds < 120) { listRepush.Add(heartBeatSAEA); existNeedReuseItem = true; } else { //说明太闲了(完全空闲两分钟了!一直没被Pop出去复用),不用发所谓心跳,直接关闭 StartDisconnect(heartBeatSAEA); GetSimplePerf().PerfClientIdleConnectionCounter.Decrement(); } } if (existNeedReuseItem) { //别因为等待信号,导致可复用连接长时间无效闲置 if (sw.ElapsedMilliseconds > 100) { break; } } cleanSignal.WaitOne(); heartBeatSAEA = thisPortKey.Pop(); } for (int i = 0; i < listRepush.Count; i++) { thisPortKey.Push(listRepush[i]); } //if (listRepush.Count > 1) // thisPortKey.BatchPush(listRepush.ToArray()); //else if (listRepush.Count.Equals(1)) // thisPortKey.Push(listRepush[0]); } alreadyChecked = true; } Thread.Sleep(waitTime); } }
private void Init() { if (!isInit) { lock (lockForPickObject) { if (!isInit) { Stopwatch sw = new Stopwatch(); sw.Start(); clientSetting = GetLocalClientSetting(); ServerCount = clientSetting.serverEndPoints.Length; timeOutByMS = clientSetting.timeOutByMS; //初始化后,不可更改! bufferManager = new BufferManager(clientSetting.bufferSize * clientSetting.opsToPreAllocate * clientSetting.numberOfSaeaForRecSend, clientSetting.bufferSize * clientSetting.opsToPreAllocate); bufferManager.InitBuffer(); //用于负责建立连接的saea,无关buffermanager,10个足够!这部分实际在ClientSocketProcessor中可以动态增加 //poolOfConnectEventArgs = new SocketAsyncEventArgPool(clientSetting.maxSimultaneousConnectOps); poolOfConnectEventArgs = new SocketAsyncEventArgPool(); //用于负责在建立好的连接上传输数据,涉及buffermanager,目前测试100~200个足够!这部分目前不支持动态增加! //因其buffermanager是事先分配好的一大块连续的固定内存区域,强烈建议不再更改,需要做好的就是事先的大小评估。 //poolOfRecSendEventArgs = new SocketAsyncEventArgPool(clientSetting.numberOfSaeaForRecSend); poolOfRecSendEventArgs = new SocketAsyncEventArgPool(); //实际负责处理相关传输数据的关键核心类 processor = new ClientSocketProcessor(poolOfConnectEventArgs, poolOfRecSendEventArgs, clientSetting.numberOfSaeaForRecSend, clientSetting.bufferSize, clientSetting.numberOfMessagesPerConnection, clientSetting.receivePrefixLength, clientSetting.useKeepAlive, "bizclient"); //由于不涉及buffermanager,可动态增长 for (int i = 0; i < clientSetting.maxSimultaneousConnectOps; i++) { SocketAsyncEventArgs connectEventArg = new SocketAsyncEventArgs(); connectEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(processor.IO_Completed); //关键负责标识saea和更关键的传输待发送的数据给传输用的saea。 ConnectOpUserToken theConnectingToken = new ConnectOpUserToken(); connectEventArg.UserToken = theConnectingToken; poolOfConnectEventArgs.Push(connectEventArg); } //涉及buffermanager,不可动态增长,需事先评估即可,负责实际的数据传输 for (int i = 0; i < clientSetting.numberOfSaeaForRecSend; i++) { SocketAsyncEventArgs eventArgObjectForPool = new SocketAsyncEventArgs(); //事先为每个saea分配固定不变的内存位置! bufferManager.SetBuffer(eventArgObjectForPool); eventArgObjectForPool.Completed += new EventHandler <SocketAsyncEventArgs>(processor.IO_Completed); ClientUserToken receiveSendToken = new ClientUserToken(eventArgObjectForPool.Offset, eventArgObjectForPool.Offset + clientSetting.bufferSize, clientSetting.receivePrefixLength, clientSetting.sendPrefixLength); //用于传递待发送的数据,一旦完成发送必须重新new一个。 receiveSendToken.CreateNewSendDataHolder(); eventArgObjectForPool.UserToken = receiveSendToken; poolOfRecSendEventArgs.Push(eventArgObjectForPool); } bufferManager.SetInitComplete(); sw.Stop(); LogManager.Log(string.Format("SocketClient Init by FirstInvoke Completed! ConsumeTime:{0} ms", sw.ElapsedMilliseconds)); isInit = true; } } } }