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(); }
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); } }