1

我正在编写一个库来简化我在未来项目中的网络编程。我希望它强大而高效,因为这将出现在我未来的几乎所有项目中。(顺便说一句,服务器和客户端都将使用我的库,所以我没有在我的问题中假设协议)我正在编写一个函数,用于从网络流中接收字符串,其中我使用 31 个字节的缓冲区和一个用于哨兵。sentinel 值将指示哪个字节(如果有)是 EOF。这是我的代码供您使用或审查...

public string getString()
    {
        string returnme = "";
        while (true)
        {
            int[] buff = new int[32];
            for (int i = 0; i < 32; i++)
            {
                buff[i] = ns.ReadByte();
            }
            if (buff[31] > 31) { /*throw some error*/}
            for (int i = 0; i < buff[31]; i++)
            {
                returnme += (char)buff[i];
            }
            if (buff[31] != 31)
            {
                break;
            }
        }
        return returnme;
    }

编辑:这是完成我正在做的事情的最佳方式(高效、实用等)吗?

4

2 回答 2

3

这是完成我正在做的事情的最佳方式(高效、实用等)吗?

不。首先,您将自己限制在 0-255 代码点范围内的字符,这还不够,其次:序列化字符串是一个已解决的问题。只需使用一个Encoding,通常是 UTF-8。作为网络流的一部分,这可能意味着“编码长度,编码数据”和“读取长度,缓冲那么多数据,解码数据”。另请注意:如果ReadByte()返回负值,您将无法正确处理 EOF 场景。

作为一个小推论,请注意string在循环中附加到 a 绝不是一个好主意。如果您确实这样做了,请使用StringBuilder. 但不要那样做。我的代码更像是(嘿,你知道,这是我从 protobuf-net 获得的实际字符串读取代码,稍微简化了一点):

// read the length         
int bytes = (int)ReadUInt32Variant(false);
if (bytes == 0) return "";

// buffer that much data
if (available < bytes) Ensure(bytes, true);

// read the string
string s = encoding.GetString(ioBuffer, ioIndex, bytes);

// update the internal buffer data
available -= bytes;
position += bytes;
ioIndex += bytes;
return s;

最后一点,我想说:如果您要发送结构化消息,请认真考虑使用专门处理这些内容的预滚动序列化 API。例如,您可以执行以下操作:

var msg = new MyMessage { Name = "abc", Value = 123, IsMagic = true };
Serializer.SerializeWithLengthPrefix(networkStream, msg);

在另一端:

var msg = Serializer.DeserializeWithLengthPrefix<MyMessage>(networkStream);
Console.WriteLine(msg.Name); // etc

任务完成。

于 2012-08-07T05:45:36.110 回答
0

我认为 tou 应该使用具有固定大小的 StringBuilder 对象以获得更好的性能。

于 2012-08-07T05:44:18.457 回答