private void ProcessConnectionError(SocketAsyncEventArgs connectEventArgs) { try { LogManager.Log(string.Format("ConnectError:{0} for {1}", connectEventArgs.SocketError, connectEventArgs.AcceptSocket != null ? connectEventArgs.AcceptSocket.RemoteEndPoint != null ? connectEventArgs.AcceptSocket.RemoteEndPoint.ToString() : "unknown remote address!" : "unknown remote address"), new Exception("Connect Error!")); ConnectOpUserToken theConnectingToken = (ConnectOpUserToken)connectEventArgs.UserToken; // If connection was refused by server or timed out or not reachable, then we'll keep this socket. // If not, then we'll destroy it. if ((connectEventArgs.SocketError != SocketError.ConnectionRefused) && (connectEventArgs.SocketError != SocketError.TimedOut) && (connectEventArgs.SocketError != SocketError.HostUnreachable)) { CloseSocket(connectEventArgs.AcceptSocket); } //返回null数据 if (ReceiveFeedbackDataComplete != null) { for (int i = 0; i < theConnectingToken.ArrayOfMessageReadyToSend.Count; i++) { ReceiveFeedbackDataCompleteEventArg arg = new ReceiveFeedbackDataCompleteEventArg(); arg.MessageTokenId = theConnectingToken.ArrayOfMessageReadyToSend[i].TokenId; arg.FeedbackData = null; LogManager.Log("ConnectionErr!", new Exception(string.Format("FeedbackError:messageTokenId:{0} 因连接错误主动关闭并返回NULL数据", arg.MessageTokenId))); ReceiveFeedbackDataComplete(this, arg); } } //it is time to release connectEventArgs object back to the pool. poolOfConnectEventArgs.Push(connectEventArgs); } catch (Exception closeErr) { LogManager.Log(string.Empty, closeErr); } finally { this.maxConcurrentConnection.Release(); } }
private void StartConnect(SocketAsyncEventArgs connectEventArgs, IPEndPoint serverEndPoint) { try { ConnectOpUserToken theConnectingToken = (ConnectOpUserToken)connectEventArgs.UserToken; theConnectingToken.ServerEndPointKey = string.Format("{0}_{1}", serverEndPoint.Address, serverEndPoint.Port); connectEventArgs.RemoteEndPoint = serverEndPoint; connectEventArgs.AcceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); bool willRaiseEvent = connectEventArgs.AcceptSocket.ConnectAsync(connectEventArgs); if (!willRaiseEvent) { ProcessConnect(connectEventArgs); } } catch (Exception startConnectErr) { this.maxConcurrentConnection.Release(); LogManager.Log("StartConnect", startConnectErr); } }
private void ProcessConnect(SocketAsyncEventArgs connectEventArgs) { ConnectOpUserToken theConnectingToken = (ConnectOpUserToken)connectEventArgs.UserToken; if (connectEventArgs.SocketError == SocketError.Success) { SocketAsyncEventArgs receiveSendEventArgs = poolOfRecSendEventArgs.Pop(); if (receiveSendEventArgs == null) { //几乎不可能发生! LogManager.Log(string.Empty, new Exception("fetch receiveSendEventArgs failed for connect")); return; } Interlocked.Increment(ref currentConnectionCount); GetSimplePerf().PerfConcurrentClientConnectionCounter.Increment(); receiveSendEventArgs.AcceptSocket = connectEventArgs.AcceptSocket; ClientUserToken receiveSendToken = (ClientUserToken)receiveSendEventArgs.UserToken; receiveSendToken.sendDataHolder.SetSendMessage(theConnectingToken.ArrayOfMessageReadyToSend); receiveSendToken.ServerEndPointKey = theConnectingToken.ServerEndPointKey; MessagePreparer.GetDataToSend(receiveSendEventArgs); receiveSendToken.startTime = theConnectingToken.ArrayOfMessageReadyToSend[0].StartTime; StartSend(receiveSendEventArgs); //release connectEventArgs object back to the pool. connectEventArgs.AcceptSocket = null; this.poolOfConnectEventArgs.Push(connectEventArgs); } else { ProcessConnectionError(connectEventArgs); } }
internal SendStatus SendMessage(List <Message> messages, IPEndPoint serverEndPoint, int currentRequestCount) { if (supportKeepAlive) { if (ReuseHeartBeatSAEA(messages, string.Format("{0}_{1}", serverEndPoint.Address, serverEndPoint.Port))) { return(SendStatus.OK_ON_STEPONE_REUSE); } } //到达配置限制数量,立即返回防止IIS线程越开越多进入假死状态。 lock (lockConcurrentStepOne) { if ((maxConnectionCount - currentConnectionCount) < 1) { return(SendStatus.CONNECTION_EXHAUST); } else if (currentRequestCount > maxConnectionCount) { return(SendStatus.TOOMANY_REQUEST); } } maxConcurrentConnection.WaitOne(); if (supportKeepAlive) { if (ReuseHeartBeatSAEA(messages, string.Format("{0}_{1}", serverEndPoint.Address, serverEndPoint.Port))) { return(SendStatus.OK_ON_STEPTWO_REUSE); } } //到达配置限制数量,立即返回防止IIS线程越开越多进入假死状态。 lock (lockConcurrentStepTwo) { if ((maxConnectionCount - currentConnectionCount) < 1) { return(SendStatus.CONNECTION_EXHAUST); } else if (currentRequestCount > maxConnectionCount) { return(SendStatus.TOOMANY_REQUEST); } } SocketAsyncEventArgs connectEventArgs = this.poolOfConnectEventArgs.Pop(); //or make a new one. if (connectEventArgs == null) { connectEventArgs = new SocketAsyncEventArgs(); connectEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed); ConnectOpUserToken theConnectingToken = new ConnectOpUserToken(); theConnectingToken.ArrayOfMessageReadyToSend = messages; connectEventArgs.UserToken = theConnectingToken; } else { ConnectOpUserToken theConnectingToken = (ConnectOpUserToken)connectEventArgs.UserToken; theConnectingToken.ArrayOfMessageReadyToSend = messages; } StartConnect(connectEventArgs, serverEndPoint); return(SendStatus.OK_ON_OPENNEW); }
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; } } } }