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

            // Keep track of how many bytes we have read, notice the + sign
            attachment.NumberOfBytesReadSoFar += (ulong)attachment.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
                    attachment.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.
                    attachment.ClientSocket.BeginReceive(attachment.ReceivingHeaderBuffer,
                                                         (int)attachment.NumberOfBytesReadSoFar,
                                                         (int)((ulong)attachment.ReceivingHeaderBuffer.LongLength -
                                                               attachment.NumberOfBytesReadSoFar),
                                                         SocketFlags.None,
                                                         OnHeaderReceived, attachment);
                    return;
                }
            }
        }
예제 #2
0
 private void ReadHeader(ClientConnectionAttachment attachment)
 {
     // BeginReceive is asynchronous, so this function call returns immediately
     // First we want the header so begin receiving the header (8 bytes long)
     attachment.ClientSocket.BeginReceive(attachment.ReceivingHeaderBuffer, 0 /*Offset*/,
                                          attachment.ReceivingHeaderBuffer.Length /* 8 bytes long to read for the header */,
                                          SocketFlags.None, OnHeaderReceived,
                                          attachment);
 }
예제 #3
0
        public void OnPendingClientConnection(IAsyncResult result)
        {
            Console.WriteLine("Connection received");
            ClientConnectionAttachment attachment = new ClientConnectionAttachment();
            Socket serverSocket = ((Socket)result.AsyncState);

            attachment.ClientSocket = serverSocket.EndAccept(result);

            // Schedule one server async Accept
            AcceptOneClient(serverSocket);

            // Schedule an async read
            ReadHeader(attachment);
        }
예제 #4
0
        private void OnPayloadReceived(IAsyncResult result)
        {
            ClientConnectionAttachment attachment = (ClientConnectionAttachment)result.AsyncState;

            // Keep track of how many bytes we have read, notice the + sign
            attachment.NumberOfBytesReadSoFar += (ulong)attachment.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
                    attachment.ClientSocket.BeginReceive(attachment.ReceivingPayloadBuffer,
                                                         (int)attachment.NumberOfBytesReadSoFar, // Offset
                                                         (int)((ulong)attachment.ReceivingPayloadBuffer.LongLength -
                                                               attachment.NumberOfBytesReadSoFar),
                                                         SocketFlags.None,
                                                         OnPayloadReceived,
                                                         attachment);
                }
                else
                {
                    OnPacketReady(attachment);

                    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(attachment);
                }
            }
            else
            {
                // This most likely means socket closed
                Console.WriteLine("Read 0 bytes");
            }
        }
예제 #5
0
        private void OnPacketReady(ClientConnectionAttachment attachment)
        {
            Notification notification = Notification.DeSerialize(attachment.ReceivingPayloadBuffer);

            Console.WriteLine("Message: {0}\nCreated At {1}", notification.Message, notification.CreatedAt);
        }