关于优化C#NET代码块的反馈

时间:2011-03-12 15:51:35

标签: c# .net optimization tcp

我花了几个小时阅读TCP服务器以及我想要实现的所需协议,最后让一切都运行得很好。我注意到代码看起来像绝对的bollocks(正确的用法?我不是英国人),并希望得到一些优化它的反馈,主要是为了重用和可读性。

数据包格式总是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 个答案:

答案 0 :(得分:3)

思想:

  • 除了少数几个,你并没有真正使用读者;否则,你需要的只是ReadByte,你可以从Stream中做到这一点,并保存一些间接/混淆
  • 手动阅读注册以避免Endianness问题
  • 逐字节读取可能很昂贵;如果可能的话,尝试通过循环读取而不是ReadByte来填充缓冲区(或者更确切地说:读取正确数量的数据)
  • 如果多条消息在同一个管道中传入,则读取到EOF可能会失败(要么破坏数据,要么永久阻止);您通常需要终结符序列或长度前缀。我更喜欢后者,因为它让你使用Read而不是ReadByte
  • 我假设你的例子中是packetSize;使用此功能 critical :分隔消息,验证您有整个消息,并拒绝过大的数据
  • 考虑异步(BeginRead)是否合适 - 有时是,有时没有;并注意,这使得处理更加棘手,因为您无法使用“使用”与async
  • 使用MemoryStream时,将.GetBuffer() 结合使用.Length比使用.ToArray()
  • 的开销更少

答案 1 :(得分:0)

跳出来的第一件事就是始终将using statement与任何实现 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();
    }
}
相关问题