Отзыв об оптимизации блока кода C # NET - PullRequest
3 голосов
/ 12 марта 2011

Я потратил довольно много часов, читая на TCP-серверах и желаемом протоколе, который я пытался реализовать, и наконец все получилось отлично.Я заметил, что код выглядит как абсолютные боллосы (это правильное использование? Я не брит), и хотел бы получить некоторые отзывы об его оптимизации, в основном для повторного использования и читабельности.

Форматы пакетов всегда int, int,int, string, string.

try
{
    BinaryReader reader = new BinaryReader(clientStream);
    int packetsize = reader.ReadInt32();
    int requestid = reader.ReadInt32();
    int serverdata = reader.ReadInt32();
    Console.WriteLine("Packet Size: {0} RequestID: {1} ServerData: {2}", packetsize, requestid, serverdata);

    List<byte> str = new List<byte>();
    byte nextByte = reader.ReadByte();

    while (nextByte != 0)
    {
        str.Add(nextByte);
        nextByte = reader.ReadByte();
    }

    // Password Sent to be Authenticated
    string string1 = Encoding.UTF8.GetString(str.ToArray());

    str.Clear();
    nextByte = reader.ReadByte();

    while (nextByte != 0)
    {
        str.Add(nextByte);
        nextByte = reader.ReadByte();
    }

    // NULL string
    string string2 = Encoding.UTF8.GetString(str.ToArray());

    Console.WriteLine("String1: {0} String2: {1}", string1, string2);

    // Reply to Authentication Request
    MemoryStream stream = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(stream);

    writer.Write((int)(1)); // Packet Size
    writer.Write((int)(requestid)); // Mirror RequestID if Authenticated, -1 if Failed
    byte[] buffer = stream.ToArray();

    clientStream.Write(buffer, 0, buffer.Length);
    clientStream.Flush();
}

Я собираюсь иметь дело и с другими типами пакетов, которые имеют одинаковый формат (int / int / int / str / str), но разные значения.Я мог бы, вероятно, создать класс пакета, но это немного выходит за рамки моих знаний о том, как применить его к этому сценарию.Если это имеет какое-то значение, это протокол, который я реализую.

http://developer.valvesoftware.com/wiki/Source_RCON_Protocol

Ответы [ 2 ]

3 голосов
/ 12 марта 2011

Мысли:

  • Вы действительно не используете ридер, за исключением нескольких целых чисел;в противном случае все, что вам нужно, - это ReadByte, который вы можете сделать из потока и сохранить некоторую косвенность / путаницу
  • читать значения вручную, чтобы избежать проблем с порядком байтов
  • чтение побайтно может быть дорогим;если возможно, попробуйте заполнить буфер (или, скорее: прочитать правильное количество данных), зацикливая на Read, а не на ReadByte
  • , если несколько сообщений поступают по одному каналу, чтение в EOF, вероятно, завершится неудачно (либоиспортить данные или заблокировать навсегда);вам обычно требуется либо терминаторная последовательность, либо префикс длины.Я предпочитаю последнее, так как оно позволяет вам использовать Read вместо ReadByte
  • Я предполагаю, что в вашем примере это packetSize; критически важно использовать это: для разделения сообщений, для проверки того, что у вас есть полное сообщение, и для запрета слишком больших данных
  • рассмотреть, подходит ли async (BeginRead) - иногда да, иногда нет;и обратите внимание, что это усложняет удаление, так как вы не можете использовать «использование» с async
  • при использовании MemoryStream, используя .GetBuffer () в сочетании с .Lengthимеет меньше накладных расходов, чем использование .ToArray ()
0 голосов
/ 12 марта 2011

Первое, что бросается в глаза - всегда использовать оператор using с любым объектом, который реализует IDisposable . Это обеспечит правильную утилизацию ваших объектов даже в случае исключения.

private void FillList(BinaryReader reader, List list)
{
    while (reader.PeekChar() != -1)
    {
        list.Add(reader.ReadByte());
    }
}

...

try
{
    int packetsize, requestid, serverdata;
    string string1, string2;
    List<byte> str = new List<byte>();

    using (BinaryReader reader = new BinaryReader(clientStream))
    {
        packetsize = reader.ReadInt32();
        requestid = reader.ReadInt32();
        serverdata = reader.ReadInt32();
        Console.WriteLine("Packet Size: {0} RequestID: {1} ServerData: {2}", packetsize, requestid, serverdata);

        FillList(reader, str);

        // Password Sent to be Authenticated
        string1 = Encoding.UTF8.GetString(str.ToArray());

        str.Clear();
        FillList(reader, str);
    }

    // NULL string
    string2 = Encoding.UTF8.GetString(str.ToArray());

    Console.WriteLine("String1: {0} String2: {1}", string1, string2);

    // Reply to Authentication Request
    using (MemoryStream stream = new MemoryStream())
    using (BinaryWriter writer = new BinaryWriter(stream))
    {

        writer.Write((int)(1)); // Packet Size
        writer.Write((int)(requestid)); // Mirror RequestID if Authenticated, -1 if Failed
        byte[] buffer = stream.ToArray();

        clientStream.Write(buffer, 0, buffer.Length);
        clientStream.Flush();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...