C# Network Stream getString method

2019-08-04 15:07发布

I'm writing a library to simplify my network programming in future projects. I'm wanting it to be robust and efficient because this will be in nearly all of my projects in the future. (BTW both the server and the client will be using my library so I'm not assuming a protocol in my question) I'm writing a function for receiving strings from a network stream where I use 31 bytes of buffer and one for sentinel. The sentinel value will indicate which byte if any is the EOF. Here's my code for your use or scrutiny...

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;
    }

Edit: Is this the best (efficient, practical, etc) to accomplish what I'm doing.

2条回答
\"骚年 ilove
2楼-- · 2019-08-04 15:27

Is this the best (efficient, practical, etc) to accomplish what I'm doing.

No. Firstly, you are limiting yourself to characters in the 0-255 code-point range, and that isn't enough, and secondly: serializing strings is a solved problem. Just use an Encoding, typically UTF-8. As part of a network stream, this probably means "encoode the length, encode the data" and "read the length, buffer that much data, decode the data". As another note: you aren't correctly handling the EOF scenario if ReadByte() returns a negative value.

As a small corollary, note that appending to a string in a loop is never a good idea; if you did do it that way, use a StringBuilder. But don't do it that way. My code would be something more like (hey, whadya know, here's my actual string-reading code from protobuf-net, simplified a bit):

// 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;

As a final note, I would say: if you are sending structured messages, give some serious consideration to using a pre-rolled serialization API that specialises in this stuff. For example, you could then just do something like:

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

and at the other end:

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

Job done.

查看更多
混吃等死
3楼-- · 2019-08-04 15:40

I think tou should use a StringBuilder object with fixed size for better performance.

查看更多
登录 后发表回答