private void CreateAndStartPort(object portOwner, int listeningPort)
        {
            if (!(portOwner is IUseP2PCommunicationsScheme))
            {
                throw (new Exception("The port owner object must implement the interface \'IUseP2PCommunicationsScheme\'"));
            }

            this._portOwnerComponent    = portOwner;
            this._ConnectedClientsTable = new Hashtable();
            this._startDateTime         = DateTime.Now;
            this._statisticsHandler     = new P2PPortStatisticsHandler();
            this._listeningPort         = listeningPort;
            string host = System.Net.Dns.GetHostName();

            this._IPAddress          = CommunicationsLibrary.Utilities.CommunicationsUtilities.GetActiveIPAddress();
            this._connectionendpoint = new IPEndPoint(this._IPAddress, this._listeningPort);

            this._prefixHandler  = new PrefixHandler();
            this._messageHandler = new DataReceptionHandler();


            Int32 totalBytes = P2PNetworkingDefinitions.DATABUFFER_SIZE * NUMBER_OF_SAEA_OBJECTS_FOR_REC_AND_SEND * NUMBER_OF_OPERATIONS_TO_ALLOCATE;
            Int32 totalBufferBytesInEachSaeaObject = P2PNetworkingDefinitions.DATABUFFER_SIZE * NUMBER_OF_OPERATIONS_TO_ALLOCATE;

            this._bufferManager = new BufferManager(totalBytes, totalBufferBytesInEachSaeaObject);

            this._poolOfRecSendEventArgs = new SocketAsyncEventArgsPool(NUMBER_OF_SAEA_OBJECTS_FOR_REC_AND_SEND);
            this._poolOfAcceptEventArgs  = new SocketAsyncEventArgsPool(NUMBER_OF_OPERATIONS_TO_ALLOCATE);

            this._maxConnectionsEnforcer = new Semaphore(MAX_CONNECTIONS, MAX_CONNECTIONS);


            //creation of the pool of SEAE Object used to handle incomming connections
            for (Int32 i = 0; i < MAX_SIMULTANEOUS_ACCEPT_OPS; i++)
            {
                SocketAsyncEventArgs SAEA = CreateNewSaeaForAccept(_poolOfAcceptEventArgs);
                this._poolOfAcceptEventArgs.Push(SAEA);
            }

            //creation of the pool of SEAE objects used for send and receive data operations
            SocketAsyncEventArgs eventArgObjectForPool;

            for (Int32 i = 0; i < NUMBER_OF_SAEA_OBJECTS_FOR_REC_AND_SEND; i++)
            {
                eventArgObjectForPool = new SocketAsyncEventArgs();
                this._bufferManager.SetBuffer(eventArgObjectForPool);
                eventArgObjectForPool.Completed += new EventHandler <SocketAsyncEventArgs>(EventHandling_IO_Completed);
                P2PPortClientConnectionHandler _P2PClientCnnHandler = new P2PPortClientConnectionHandler(eventArgObjectForPool, eventArgObjectForPool.Offset, eventArgObjectForPool.Offset + P2PNetworkingDefinitions.DATABUFFER_SIZE, P2PNetworkingDefinitions.DATA_SEND_RECEIVE_PREFIX_LENGHT, P2PNetworkingDefinitions.DATA_SEND_RECEIVE_PREFIX_LENGHT);
                _P2PClientCnnHandler.CreateNewDataReceivedBuffer(P2PNetworkingDefinitions.DATABUFFER_SIZE);
                eventArgObjectForPool.UserToken = _P2PClientCnnHandler;
                this._poolOfRecSendEventArgs.Push(eventArgObjectForPool);
            }

            //creation of the socker and binging to a listening port
            _listenSocket = new Socket(this._connectionendpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            _listenSocket.Bind(this._connectionendpoint);
            _listenSocket.Listen(BACK_LOG);
            StartAccept();
        }
Example #2
0
        private void ProcessReceive(SocketAsyncEventArgs receiveSendEventArgs)
        {
            ServerUserToken receiveSendToken = (ServerUserToken)receiveSendEventArgs.UserToken;

            if (receiveSendEventArgs.SocketError != SocketError.Success)
            {
                if (receiveSendEventArgs.SocketError != SocketError.ConnectionReset)
                {
                    LogManager.Log(string.Format("ProcessReceive ERROR: {0}, receiveSendToken sessionid:{1}", receiveSendEventArgs.SocketError, receiveSendToken.serverSession.SessionId));
                }

                receiveSendToken.Reset();
                CloseClientSocket(receiveSendEventArgs);

                return;
            }

            if (receiveSendEventArgs.BytesTransferred == 0)
            {
                receiveSendToken.Reset();
                CloseClientSocket(receiveSendEventArgs);

                return;
            }

            int remainingBytesToProcess = receiveSendEventArgs.BytesTransferred;

            //LogManager.Log(string.Format("getlength:{0} on {1} with prefixDoneCount:{2}", remainingBytesToProcess, receiveSendEventArgs.AcceptSocket.RemoteEndPoint,receiveSendToken.receivedPrefixBytesDoneCount));

            if (receiveSendToken.receivedPrefixBytesDoneCount < this.receivePrefixLength)
            {
                bool getLengthInfoSuccessfully = false;

                remainingBytesToProcess = PrefixHandler.HandlePrefix(receiveSendEventArgs, receiveSendToken, remainingBytesToProcess, ref getLengthInfoSuccessfully);

                if (remainingBytesToProcess == 0)
                {
                    // We need to do another receive op, since we do not have
                    // the message yet, but remainingBytesToProcess == 0.
                    StartReceive(receiveSendEventArgs);

                    return;
                }
            }

            bool incomingTcpMessageIsReady = MessageHandler.HandleMessage(receiveSendEventArgs, receiveSendToken, remainingBytesToProcess);

            if (incomingTcpMessageIsReady == true)
            {
                if (receiveSendToken.dataMessageReceived != null && receiveSendToken.dataMessageReceived.Length > 0)
                {
                    byte[] processResult = this.dataProcessor(receiveSendToken.dataMessageReceived);

                    MessagePreparer.GetDataToSend(receiveSendEventArgs, processResult);

                    //开始下次接收
                    receiveSendToken.CreateNewServerSession(receiveSendEventArgs);
                    receiveSendToken.dataMessageReceived = null;
                    receiveSendToken.Reset();

                    //调整了Reset位置到此语句前面执行,这样确保一个连接多次发送不会出问题了
                    //即便processResult为byte[0],也会返回类似sessionid,transessionid头信息回客户端
                    StartSend(receiveSendEventArgs);
                }
                else
                {
                    if (!supportKeepAlive)
                    {
                        receiveSendToken.Reset();
                        CloseClientSocket(receiveSendEventArgs);
                        return;
                    }
                    else
                    {
                        //只是个万全做法,不应该有此逻辑,即传输内容为空!
                        receiveSendToken.CreateNewServerSession(receiveSendEventArgs);
                        receiveSendToken.dataMessageReceived = null;
                        receiveSendToken.Reset();

                        StartReceive(receiveSendEventArgs);
                    }
                }
            }
            else
            {
                receiveSendToken.receiveMessageOffset     = receiveSendToken.bufferOffsetReceive;
                receiveSendToken.recPrefixBytesDoneThisOp = 0;

                StartReceive(receiveSendEventArgs);
            }
        }
        private void ProcessReceive(SocketAsyncEventArgs receiveSendEventArgs)
        {
            ClientUserToken receiveSendToken = (ClientUserToken)receiveSendEventArgs.UserToken;

            if (receiveSendEventArgs.SocketError != SocketError.Success)
            {
                LogManager.Log(string.Format("SocketError:{0} on {1}", receiveSendEventArgs.SocketError, receiveSendEventArgs.AcceptSocket.RemoteEndPoint), new ArgumentException("SocketError"));
                receiveSendToken.Reset();
                StartDisconnect(receiveSendEventArgs);
                return;
            }

            if (receiveSendEventArgs.BytesTransferred == 0)
            {
                LogManager.Log(string.Format("SocketError:{0} on {1} for byte transfer equal zero", receiveSendEventArgs.SocketError, receiveSendEventArgs.AcceptSocket.RemoteEndPoint), new ArgumentException("BytesTransferred"));
                receiveSendToken.Reset();
                StartDisconnect(receiveSendEventArgs);
                return;
            }

            int remainingBytesToProcess = receiveSendEventArgs.BytesTransferred;


            // If we have not got all of the prefix then we need to work on it.
            // receivedPrefixBytesDoneCount tells us how many prefix bytes were
            // processed during previous receive ops which contained data for
            // this message. (In normal use, usually there will NOT have been any
            // previous receive ops here. So receivedPrefixBytesDoneCount would be 0.)
            if (receiveSendToken.receivedPrefixBytesDoneCount < this.prefixHandleLength)
            {
                bool getLengthInfoSuccessfully = false;

                remainingBytesToProcess = PrefixHandler.HandlePrefix(receiveSendEventArgs, receiveSendToken, remainingBytesToProcess, ref getLengthInfoSuccessfully);

                if (remainingBytesToProcess == 0)
                {
                    // We need to do another receive op, since we do not have
                    // the message yet.
                    StartReceive(receiveSendEventArgs);

                    //Jump out of the method, since there is no more data.
                    return;
                }
            }

            // If we have processed the prefix, we can work on the message now.
            // We'll arrive here when we have received enough bytes to read
            // the first byte after the prefix.
            bool incomingTcpMessageIsReady = MessageHandler.HandleMessage(receiveSendEventArgs, receiveSendToken, remainingBytesToProcess);

            if (incomingTcpMessageIsReady == true)
            {
                //将数据写入缓存字典中
                if (ReceiveFeedbackDataComplete != null)
                {
                    ReceiveFeedbackDataCompleteEventArg arg = new ReceiveFeedbackDataCompleteEventArg();
                    arg.MessageTokenId = receiveSendToken.messageTokenId;
                    arg.FeedbackData   = receiveSendToken.dataMessageReceived;

                    if (arg.FeedbackData == null)
                    {
                        LogManager.Log("服务端返回数据为NULL!", new ArgumentException(string.Format("FeedbackError:arg.FeedbackData on {0}", arg.MessageTokenId)));
                    }

                    ReceiveFeedbackDataComplete(this, arg);
                }

                receiveSendToken.Reset();

                //receiveSendToken.sendDataHolder.NumberOfMessageHadSent在ProcessSend成功后修正加一
                //这里是等待回传数据后,开始下次发送前的判断,直至将List<Message>全部发送完毕为止,
                //List<Message>中的数量由调用方控制
                if (receiveSendToken.sendDataHolder.ArrayOfMessageToSend.Count > receiveSendToken.sendDataHolder.NumberOfMessageHadSent)
                {
                    MessagePreparer.GetDataToSend(receiveSendEventArgs);
                    StartSend(receiveSendEventArgs);
                }
                else
                {
                    if (!supportKeepAlive)
                    {
                        receiveSendToken.sendDataHolder.ArrayOfMessageToSend = null;
                        //disconnect中会重新new一个senddataholder,numberofmessagehadsent即清零
                        StartDisconnect(receiveSendEventArgs);
                    }
                    else
                    {
                        //加入support keepalive机制处理逻辑
                        SetToHeartBeatStatus(receiveSendEventArgs, receiveSendToken);
                    }
                }
            }
            else
            {
                receiveSendToken.receiveMessageOffset     = receiveSendToken.bufferOffsetReceive;
                receiveSendToken.recPrefixBytesDoneThisOp = 0;

                StartReceive(receiveSendEventArgs);
            }
        }