public void SendPacket(BlendFarmMessage message)
        {
            Type t = message.GetType();
            BlendFarmHeaderAttribute attr = t.GetCustomAttribute <BlendFarmHeaderAttribute>();

            if (attr != null && BlendFarmMessage.HasPackageType(attr.Header))
            {
                string paddedHeader = attr.Header.PadRight(MAX_HEADER_SIZE, '_');
                byte[] header       = Encoding.UTF8.GetBytes(paddedHeader);

                if (header.Length != MAX_HEADER_SIZE)
                {
                    throw new ArgumentException($"Header cannot be more than {MAX_HEADER_SIZE} characters long, Was {header.Length}");
                }

                byte[] body = null;
                try
                {
                    body = BinaryParser.Serialize(message);
                }
                catch (Exception ex)
                {
                    throw new InvalidDataException($"Failed to serialize {t.Name}");
                }

                byte[] size = BinaryParser.Serialize(body.Length);

                Send((str) =>
                {
                    str.Write(header, 0, MAX_HEADER_SIZE);
                    str.Write(size, 0, 4);
                    str.Write(body, 0, body.Length);
                });
            }
        }
        public void HandlePacket(string header, BinaryReader reader)
        {
            if (!BlendFarmMessage.HasPackageType(header))
            {
                return;
            }

            Type             packetType = BlendFarmMessage.GetPackageType(header);
            BlendFarmMessage req        = null;

            try
            {
                req = (BlendFarmMessage)BinaryParser.Deserialize(reader, packetType);
            }
            catch (Exception ex)
            {
                throw new InvalidDataException($"Failed to parse {packetType.Name} due to:" + ex.Message);
            }

            Task.Run(() =>
            {
                try
                {
                    if (_handlers.ContainsKey(header))
                    {
                        MethodInfo method = _handlers[header];
                        object resp       = method.Invoke(this, new object[] { req });

                        if (resp != null && resp is BlendFarmMessage)
                        {
                            BlendFarmMessage bfresp = ((BlendFarmMessage)resp);
                            if (req.RequestID != null)
                            {
                                bfresp.ResponseID = req.RequestID;
                            }

                            SendPacket((BlendFarmMessage)resp);
                        }
                    }
                    else
                    {
                        OnMessage?.Invoke(this, req);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Exception in handling [{header}] due to {ex.Message}");
                }
            });
        }