예제 #1
0
        private void ReadCallback(IAsyncResult ar)
        {
            ConnectedClient player = (ConnectedClient)ar.AsyncState;

            try
            {
                Socket handler = player.workSocket;

                // Read data from the client socket.
                int bytesRead = handler.EndReceive(ar);

                //Logger.Debug($"READ {bytesRead} BYTES");

                if (bytesRead > 0)
                {
                    var currentBytes = new byte[bytesRead];
                    Buffer.BlockCopy(player.buffer, 0, currentBytes, 0, bytesRead);

                    player.accumulatedBytes.AddRange(currentBytes);
                    if (player.accumulatedBytes.Count >= Packet.packetHeaderSize)
                    {
                        //If we're not at the start of a packet, increment our position until we are, or we run out of bytes
                        var accumulatedBytes = player.accumulatedBytes.ToArray();
                        while (!Packet.StreamIsAtPacket(accumulatedBytes) && accumulatedBytes.Length >= Packet.packetHeaderSize)
                        {
                            player.accumulatedBytes.RemoveAt(0);
                            accumulatedBytes = player.accumulatedBytes.ToArray();
                        }

                        while (accumulatedBytes.Length >= Packet.packetHeaderSize && Packet.PotentiallyValidPacket(accumulatedBytes))
                        {
                            Packet readPacket = null;
                            try
                            {
                                readPacket = Packet.FromBytes(accumulatedBytes);
                                PacketReceived?.Invoke(player, readPacket);
                            }
                            catch (Exception e)
                            {
                                Logger.Error(e.Message);
                                Logger.Error(e.StackTrace);
                            }

                            //Remove the bytes which we've already used from the accumulated List
                            //If the packet failed to parse, skip the header so that the rest of the packet is consumed by the above vailidity check on the next run
                            player.accumulatedBytes.RemoveRange(0, readPacket?.Size ?? Packet.packetHeaderSize);
                            accumulatedBytes = player.accumulatedBytes.ToArray();
                        }
                    }

                    // Not all data received. Get more.
                    handler.BeginReceive(player.buffer, 0, ConnectedClient.BufferSize, 0, new AsyncCallback(ReadCallback), player);
                }
                else
                {
                    //Reading zero bytes is a sign of disconnect
                    ClientDisconnected_Internal(player);
                }
            }
            catch (Exception e)
            {
                Logger.Debug(e.ToString());
                ClientDisconnected_Internal(player);
            }
        }