Ejemplo n.º 1
0
        public Int32 HandlePrefix(SocketAsyncEventArgs e, DataHoldingUserToken receiveSendToken, Int32 remainingBytesToProcess)
        {            
            //receivedPrefixBytesDoneCount tells us how many prefix bytes were
            //processed during previous receive ops which contained data for 
            //this message. Usually there will NOT have been any previous 
            //receive ops here. So in that case,
            //receiveSendToken.receivedPrefixBytesDoneCount would equal 0.
            //Create a byte array to put the new prefix in, if we have not
            //already done it in a previous loop.
            if (receiveSendToken.receivedPrefixBytesDoneCount == 0)
            { 
                receiveSendToken.byteArrayForPrefix = new Byte[receiveSendToken.receivePrefixLength];
            }

            // If this next if-statement is true, then we have received >=
            // enough bytes to have the prefix. So we can determine the 
            // length of the message that we are working on.
            if (remainingBytesToProcess >= receiveSendToken.receivePrefixLength - receiveSendToken.receivedPrefixBytesDoneCount)
            { 
                //Now copy that many bytes to byteArrayForPrefix.
                //We can use the variable receiveMessageOffset as our main
                //index to show which index to get data from in the TCP
                //buffer.
                Buffer.BlockCopy(e.Buffer, receiveSendToken.receiveMessageOffset - receiveSendToken.receivePrefixLength + receiveSendToken.receivedPrefixBytesDoneCount, receiveSendToken.byteArrayForPrefix, receiveSendToken.receivedPrefixBytesDoneCount, receiveSendToken.receivePrefixLength - receiveSendToken.receivedPrefixBytesDoneCount);

                remainingBytesToProcess = remainingBytesToProcess - receiveSendToken.receivePrefixLength + receiveSendToken.receivedPrefixBytesDoneCount;

                receiveSendToken.recPrefixBytesDoneThisOp = receiveSendToken.receivePrefixLength - receiveSendToken.receivedPrefixBytesDoneCount;

                receiveSendToken.receivedPrefixBytesDoneCount = receiveSendToken.receivePrefixLength;

                receiveSendToken.lengthOfCurrentIncomingMessage = BitConverter.ToInt32(receiveSendToken.byteArrayForPrefix, 0);
                if (receiveSendToken.lengthOfCurrentIncomingMessage == -100) return receiveSendToken.lengthOfCurrentIncomingMessage;
                
                
            }

            //This next else-statement deals with the situation 
            //where we have some bytes
            //of this prefix in this receive operation, but not all.
            else
            {
                
                //Write the bytes to the array where we are putting the
                //prefix data, to save for the next loop.
                Buffer.BlockCopy(e.Buffer, receiveSendToken.receiveMessageOffset - receiveSendToken.receivePrefixLength + receiveSendToken.receivedPrefixBytesDoneCount, receiveSendToken.byteArrayForPrefix, receiveSendToken.receivedPrefixBytesDoneCount, remainingBytesToProcess);

                receiveSendToken.recPrefixBytesDoneThisOp = remainingBytesToProcess;
                receiveSendToken.receivedPrefixBytesDoneCount += remainingBytesToProcess;
                remainingBytesToProcess = 0;
            }

            // This section is needed when we have received
            // an amount of data exactly equal to the amount needed for the prefix,
            // but no more. And also needed with the situation where we have received
            // less than the amount of data needed for prefix. 
            if (remainingBytesToProcess == 0)
            {   
                receiveSendToken.receiveMessageOffset = receiveSendToken.receiveMessageOffset - receiveSendToken.recPrefixBytesDoneThisOp;
                receiveSendToken.recPrefixBytesDoneThisOp = 0;
            }
            return remainingBytesToProcess;
        }
Ejemplo n.º 2
0
 public ReceiveArgs(DataHoldingUserToken token)
 {
     this.Token = token;
 }
Ejemplo n.º 3
0
        //____________________________________________________________________________
        // initializes the server by preallocating reusable buffers and 
        // context objects (SocketAsyncEventArgs objects).  
        //It is NOT mandatory that you preallocate them or reuse them. But, but it is 
        //done this way to illustrate how the API can 
        // easily be used to create reusable objects to increase server performance.

        public void Init()
        {
            //if (Program.watchProgramFlow == true)   //for testing
            //{
            //    Program.testWriter.WriteLine("Init method");
            //}
            //if (Program.watchThreads == true)   //for testing
            //{
            //    DealWithThreadsForTesting("Init()");
            //}

            // Allocate one large byte buffer block, which all I/O operations will 
            //use a piece of. This gaurds against memory fragmentation.
            this.theBufferManager.InitBuffer();
            //this.theBufferManagerSend.InitBuffer();

            //if (Program.watchProgramFlow == true)   //for testing
            //{
            //    Program.testWriter.WriteLine("Starting creation of accept SocketAsyncEventArgs pool:");
            //}

            // preallocate pool of SocketAsyncEventArgs objects for accept operations           
            for (Int32 i = 0; i < this.socketListenerSettings.MaxAcceptOps; i++)
            {
                // add SocketAsyncEventArg to the pool
                this.poolOfAcceptEventArgs.Push(CreateNewSaeaForAccept(poolOfAcceptEventArgs));
            }

            //The pool that we built ABOVE is for SocketAsyncEventArgs objects that do
            // accept operations. 
            //Now we will build a separate pool for SAEAs objects 
            //that do receive/send operations. One reason to separate them is that accept
            //operations do NOT need a buffer, but receive/send operations do. 
            //ReceiveAsync and SendAsync require
            //a parameter for buffer size in SocketAsyncEventArgs.Buffer.
            // So, create pool of SAEA objects for receive/send operations.
            SocketAsyncEventArgs eventArgRecObjectForPool;
            //SocketAsyncEventArgs eventArgSendObjectForPool;

            //if (Program.watchProgramFlow == true)   //for testing
            //{
            //    Program.testWriter.WriteLine("Starting creation of receive/send SocketAsyncEventArgs pool");
            //}

            Int32 tokenId;

            for (Int32 i = 0; i < this.socketListenerSettings.NumberOfSaeaForRecSend; i++)
            {
                //Allocate the SocketAsyncEventArgs object for this loop, 
                //to go in its place in the stack which will be the pool
                //for receive/send operation context objects.
                eventArgRecObjectForPool = new SocketAsyncEventArgs();
                //eventArgSendObjectForPool = new SocketAsyncEventArgs();

                // assign a byte buffer from the buffer block to 
                //this particular SocketAsyncEventArg object
                this.theBufferManager.SetBuffer(eventArgRecObjectForPool);
                //this.theBufferManagerSend.SetBuffer(eventArgSendObjectForPool);
                int tid = poolOfRecEventArgs.AssignTokenId();
                tokenId = tid + 1000000;

                //Attach the SocketAsyncEventArgs object
                //to its event handler. Since this SocketAsyncEventArgs object is 
                //used for both receive and send operations, whenever either of those 
                //completes, the IO_Completed method will be called.
                eventArgRecObjectForPool.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
                //eventArgSendObjectForPool.Completed += new EventHandler<SocketAsyncEventArgs>(IO_CompletedSend);

                //We can store data in the UserToken property of SAEA object.
                // DataHoldingUserToken theTempReceiveSendUserToken = new DataHoldingUserToken(eventArgRecObjectForPool, eventArgRecObjectForPool.Offset, eventArgRecObjectForPool.Offset + this.socketListenerSettings.BufferSize, this.socketListenerSettings.ReceivePrefixLength, this.socketListenerSettings.SendPrefixLength, tokenId);
                DataHoldingUserToken theTempReceiveSendUserToken = new DataHoldingUserToken(eventArgRecObjectForPool, eventArgRecObjectForPool.Offset, eventArgRecObjectForPool.Offset + this.socketListenerSettings.BufferSize, this.socketListenerSettings.ReceivePrefixLength, this.socketListenerSettings.SendPrefixLength, tokenId);

                //We'll have an object that we call DataHolder, that we can remove from
                //the UserToken when we are finished with it. So, we can hang on to the
                //DataHolder, pass it to an app, serialize it, or whatever.
                theTempReceiveSendUserToken.CreateNewDataHolder();

                eventArgRecObjectForPool.UserToken = theTempReceiveSendUserToken;
                //eventArgSendObjectForPool.UserToken = theTempReceiveSendUserToken;

                // add this SocketAsyncEventArg object to the pool.
                this.poolOfRecEventArgs.Push(eventArgRecObjectForPool);
                //this.poolOfSendEventArgs.Push(eventArgSendObjectForPool);
            }
        }
Ejemplo n.º 4
0
        public bool HandleMessage(SocketAsyncEventArgs receiveSendEventArgs, DataHoldingUserToken receiveSendToken, Int32 remainingBytesToProcess)
        {
            bool incomingTcpMessageIsReady = false;
            
            //Create the array where we'll store the complete message, 
            //if it has not been created on a previous receive op. 
            Log.Info("HandleMessage:接收到的数据长度为:remainingBytesToProcess:" + remainingBytesToProcess + "receiveSendToken.receivedMessageBytesDoneCount:" + receiveSendToken.receivedMessageBytesDoneCount+"receiveSendToken.lengthOfCurrentIncomingMessage:" + receiveSendToken.lengthOfCurrentIncomingMessage);
            if (receiveSendToken.receivedMessageBytesDoneCount == 0)
            {             
                receiveSendToken.theDataHolder.dataMessageReceived = new Byte[receiveSendToken.lengthOfCurrentIncomingMessage];
            }


            // Remember there is a receiveSendToken.receivedPrefixBytesDoneCount
            // variable, which allowed us to handle the prefix even when it
            // requires multiple receive ops. In the same way, we have a 
            // receiveSendToken.receivedMessageBytesDoneCount variable, which
            // helps us handle message data, whether it requires one receive
            // operation or many.
            if (remainingBytesToProcess + receiveSendToken.receivedMessageBytesDoneCount == receiveSendToken.lengthOfCurrentIncomingMessage)
            {
                // If we are inside this if-statement, then we got 
                // the end of the message. In other words,
                // the total number of bytes we received for this message matched the 
                // message length value that we got from the prefix.

                //if (Program.watchProgramFlow == true)   //for testing
                //{
                //    Program.testWriter.WriteLine("MessageHandler, length is right for " + receiveSendToken.TokenId);
                //}

                // Write/append the bytes received to the byte array in the 
                // DataHolder object that we are using to store our data.
                Buffer.BlockCopy(receiveSendEventArgs.Buffer, receiveSendToken.receiveMessageOffset, receiveSendToken.theDataHolder.dataMessageReceived, receiveSendToken.receivedMessageBytesDoneCount, remainingBytesToProcess);
                Log.Info("HandleMessage:incomingTcpMessageIsReady 完成");
                incomingTcpMessageIsReady = true;
            }

            else
            {
                // If we are inside this else-statement, then that means that we
                // need another receive op. We still haven't got the whole message,
                // even though we have examined all the data that was received.
                // Not a problem. In SocketListener.ProcessReceive we will just call
                // StartReceive to do another receive op to receive more data.

                //if (Program.watchProgramFlow == true)   //for testing
                //{
                //    Program.testWriter.WriteLine(" MessageHandler, length is short for " + receiveSendToken.TokenId);
                //}
                try
                {
                    Buffer.BlockCopy(receiveSendEventArgs.Buffer, receiveSendToken.receiveMessageOffset, receiveSendToken.theDataHolder.dataMessageReceived, receiveSendToken.receivedMessageBytesDoneCount, remainingBytesToProcess);
                }
                catch (Exception e)
                {
                    Log.Error("receiveSendEventArgs.Buffer.Length:" + receiveSendEventArgs.Buffer.Length + " receiveSendToken.receiveMessageOffset:" + receiveSendToken.receiveMessageOffset + " receiveSendToken.theDataHolder.dataMessageReceived.Length:" + receiveSendToken.theDataHolder.dataMessageReceived.Length + " receiveSendToken.receivedMessageBytesDoneCount:" + receiveSendToken.receivedMessageBytesDoneCount + " remainingBytesToProcess:" + remainingBytesToProcess + " " + e.Message + " 接收到的数据长度为:" + receiveSendToken.lengthOfCurrentIncomingMessage + " receiveSendToken.receivedPrefixBytesDoneCount:" + receiveSendToken.receivedPrefixBytesDoneCount);
                    throw;
                }
                receiveSendToken.receiveMessageOffset = receiveSendToken.receiveMessageOffset - receiveSendToken.recPrefixBytesDoneThisOp;
                
                receiveSendToken.receivedMessageBytesDoneCount += remainingBytesToProcess;
                Log.Info("HandleMessage:持续接收中: receiveSendToken.receivedMessageBytesDoneCount=" + receiveSendToken.receivedMessageBytesDoneCount);

            } 
            return incomingTcpMessageIsReady;
        }
Ejemplo n.º 5
0
        //____________________________________________________________________________
        //Display thread info.
        //Note that there is NOT a 1:1 ratio between managed threads 
        //and system (native) threads.
        //
        //Overloaded.
        //Use this one after the DataHoldingUserToken is available.
        //
        private void DealWithThreadsForTesting(string methodName, DataHoldingUserToken receiveSendToken)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(" In " + methodName + ", receiveSendToken id " + receiveSendToken.TokenId + ". Thread id " + Thread.CurrentThread.ManagedThreadId + ". Socket handle " + receiveSendToken.socketHandleNumber + ".");
            sb.Append(DealWithNewThreads());

            Program.testWriter.WriteLine(sb.ToString());
        }