コード例 #1
0
        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();
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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);
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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;
                    }
                }
            }
        }