从流中快速处理数据包

时间:2016-09-13 08:55:15

标签: c# sockets tcpclient networkstream packets

第一个背景。我有一个相机,我的应用程序通过以太网电缆连接到它,它根据我发送的命令执行操作,并返回命令响应。

如果我以相机触发命令为例。 如果我将相机发送到T1'相机将会拍照。所有命令都使用开始和结束字符来标记包的开始和结束,因此我发送的完整数据包将如下所示

(炭)0x02T1(炭)0×03

以(char)0x02作为数据包的开头,(char)0x03作为包的结尾。

然后,相机将拍摄照片并发回相同的命令,说它已完成。您还可以将相机设置为在拍摄照片时发回一些数据。在我的情况下,我让相机检查几个区域,我想要检查一些值。

所以相机的回归就像是' T1'然后说' 1,1,500,20,300'

关于问题。我正在使用`function AnticipatedSyncFunction(){ var ret; setTimeout(function(){ var startdate = new Date() ret = "hello" + startdate; },3000); while(ret === undefined) { require('deasync').runLoopOnce(); } return ret; } var output = AnticipatedSyncFunction(); var startdate = new Date() console.log(startdate) console.log("output="+output);` TcpClient进行通信,但我正在努力处理接收端的数据包。我尝试了各种方法,但它们似乎很慢或者不能保证我得到所有数据。

首先,我需要能够读取所有数据并确保拥有所有数据的内容。

其次,我需要能够处理数据并分成数据包的东西,并尽可能快地完成。

这只是我尝试过的一种方法,并且完全归功于制作NetworkStream的人。我确定我在这里找到了它。

StreamReaderExtensions

和我的处理方法。 internal static class StreamReaderExtensions { public static IEnumerable<string> ReadUntil(this StreamReader reader, string delimiter) { List<char> buffer = new List<char>(); CircularBuffer<char> delim_buffer = new CircularBuffer<char>(delimiter.Length); while (reader.Peek() >= 0) { char c = (char)reader.Read(); delim_buffer.Enqueue(c); if (delim_buffer.ToString() == delimiter) { if (buffer.Count > 0) { yield return new String(buffer.ToArray()); buffer.Clear(); } continue; } buffer.Add(c); } } private class CircularBuffer<T> : Queue<T> { private int _capacity; public CircularBuffer(int capacity) : base(capacity) { _capacity = capacity; } new public void Enqueue(T item) { if (base.Count == _capacity) { base.Dequeue(); } base.Enqueue(item); } public override string ToString() { List<String> items = new List<string>(); foreach (var x in this) { items.Add(x.ToString()); }; return String.Join("", items); } } } _stream

TcpClient.GetStream()

1 个答案:

答案 0 :(得分:0)

我制作了一些伪代码,我没有测试过,但它可能会给你一个方向。 这不能是静态的

char[] _buffer = new char[4 * 1024 * 1024];
int currentPosition;

public bool ReadNext(StreamReader reader, char delimiter, out string value)
{
    // read as many chars from the stream.
    int charsRead = reader.ReadBlock(_buffer, currentPosition, _buffer.Length - currentPosition);

    // keep track of the current position.
    currentPosition += charsRead;

    // find the first delimiter.
    for (int i = 0; i < currentPosition; i++)
    {
        if (_buffer[i] == delimiter)
        {
            // a complete packet was found, copy it to a string.
            value = new string(_buffer, 0, i);
            // move the rest of the data back to the start of the buffer.
            Array.Copy(_buffer, i, _buffer, 0, _buffer.Length - i);
            // decrease the current position also.
            currentPosition -= i;
            // return true because you have data.
            return true;
        }
    }

    // no complete packet was found.
    value = String.Empty;
    return false;
}

用法:

string data;

while(true)
{
    if(ReadNext(reader, (char)0x03, out data))
        MessageBox.Show(data);
}

就像我说未经测试一样,这只是一个脑力......你可能需要添加对数据包开始的检查。