예제 #1
0
        private void OnPayloadReceived(IAsyncResult result)
        {
            ReadAttachment attachment = (ReadAttachment)result.AsyncState;

            // Keep track of how many bytes we have read, notice the + sign
            attachment.NumberOfBytesReadSoFar += (ulong)ClientSocket.EndReceive(result);

            if (attachment.NumberOfBytesReadSoFar > 0)
            {
                // If we are here that means the Header was already Read
                // A common bug is to do if(NumberOfBytesReadSoFar < ReceivingPayloadBuffer.Length)
                // that is wrong when reusing the ReceivingPayloadBuffer (which we are in this case)
                // because what would happen if wew are reusing a payload buffer bigger than
                // the currently expected payload size? well, you guessed it, we would be mixing
                // to packets in the same buffer...
                if (attachment.NumberOfBytesReadSoFar < attachment.ExpectedReceivingPayloadLength)
                {
                    // If we have not filled the buffer that means we have to keep reading
                    // Obviously we don't want to override what we have read so far, so adjust
                    // the offset, and also the length because now we have to take into account
                    // what we have read so far
                    ClientSocket.BeginReceive(attachment.ReceivingPayloadBuffer,
                                              (int)attachment.NumberOfBytesReadSoFar, // Offset
                                              (int)((ulong)attachment.ReceivingPayloadBuffer.LongLength -
                                                    attachment.NumberOfBytesReadSoFar),
                                              SocketFlags.None,
                                              OnPayloadReceived,
                                              attachment);
                }
                else
                {
                    IFormatter   formatter    = new BinaryFormatter();
                    MemoryStream memoryStream = new MemoryStream(attachment.ReceivingPayloadBuffer);
                    Packet       packet       = (Packet)formatter.Deserialize(memoryStream);


                    attachment.NumberOfBytesReadSoFar = 0;
                    // Empty the byte[] arrays, this is actually not needed, but it is a good practice
                    Array.Clear(attachment.ReceivingHeaderBuffer, 0, attachment.ReceivingHeaderBuffer.Length);
                    Array.Clear(attachment.ReceivingPayloadBuffer, 0, attachment.ReceivingPayloadBuffer.Length);

                    // Read another packet
                    ReadHeader();

                    OnPacketReceived(packet);
                }
            }
            else
            {
                // This most likely means socket closed
                Console.WriteLine("Read 0 bytes");
            }
        }
예제 #2
0
        private void OnHeaderReceived(IAsyncResult result)
        {
            try
            {
                ReadAttachment attachment = (ReadAttachment)result.AsyncState;
                // Keep track of how many bytes we have read, notice the + sign
                attachment.NumberOfBytesReadSoFar += (ulong)ClientSocket.EndReceive(result);

                if (attachment.NumberOfBytesReadSoFar > 0)
                {
                    if (attachment.NumberOfBytesReadSoFar == (ulong)attachment.ReceivingHeaderBuffer.Length)
                    {
                        // We have read the header, now let's proceed to read the payload

                        // Reset this, because we are gonna use it
                        // to keep track of number of bytes read for the payload, instead of Header
                        attachment.NumberOfBytesReadSoFar = 0;

                        attachment.ExpectedReceivingPayloadLength =
                            BitConverter.ToUInt64(attachment.ReceivingHeaderBuffer, 0);

                        // You have to make sure payloadLength is > 0 and < than what you think would be too big,
                        // just to keep hackers away which I don't for this simple snippet
                        // but keep in mind that serialized C# Objects are big ...

                        // Now a decision, should I create a new byte[] or just reuse the one used for the previous packet?
                        if (attachment.ReceivingPayloadBuffer == null || // If the payload byte[] is null
                            // or its capacity is less than we need
                            (ulong)attachment.ReceivingPayloadBuffer.Length <
                            attachment.ExpectedReceivingPayloadLength)
                        {
                            // Then create a new one
                            attachment.ReceivingPayloadBuffer = new byte[attachment.ExpectedReceivingPayloadLength];
                        }

                        // Begin reading the payload now
                        ClientSocket.BeginReceive(attachment.ReceivingPayloadBuffer, 0,
                                                  (int)attachment.ExpectedReceivingPayloadLength, SocketFlags.None, OnPayloadReceived,
                                                  attachment);
                        return;
                    }
                    else
                    {
                        // We are not done reading the header, keep reading it
                        // For example if have just read 3 bytes, now we are expecting 5 more bytes (because we know
                        // the header should be 8 bytes long, so we begin reading and filling the buffer from offset 3.
                        // So: NumberOfBytesReadSoFar would be 3,
                        // second parameter would be NumberOfBytesReadSoFar(3),
                        // forth parameter would be 5 (because of: 8 - 3).
                        // Hope make sense, it is easy.
                        ClientSocket.BeginReceive(attachment.ReceivingHeaderBuffer,
                                                  (int)attachment.NumberOfBytesReadSoFar,
                                                  (int)((ulong)attachment.ReceivingHeaderBuffer.LongLength -
                                                        attachment.NumberOfBytesReadSoFar),
                                                  SocketFlags.None,
                                                  OnHeaderReceived, attachment);
                        return;
                    }
                }
            }
            catch (Exception exception)
            {
                OnDisconnected(exception);
            }
        }