【问题标题】:UWP TCP read large messagesUWP TCP 读取大消息
【发布时间】:2017-09-30 11:01:40
【问题描述】:

我正在尝试从 TCP 套接字读取字符串。服务器(我无权访问)发送的字符串可以比 BUFFER_SIZE 更小(只有 3 个字符)或更长(> 10.000 个字符)。

为此,我正在使用以下方法,该方法在单独的任务(线程)中连续运行。一旦它读取到一个有效的字符串,它就会触发一个事件,主任务订阅了该事件 [...]

外部取消 reader.ReadAsync(...) 需要 cTS (CancellationTokenSource)

private readonly int BUFFER_SIZE = 4096;
private StreamSocket tcpSocket;
private StreamReader reader;
private CancellationTokenSource cTS;

public string readMessageFromServer()
{
    string result = "";
    while(true)
    {
        char[] buffer = new char[BUFFER_SIZE];
        cTS = new CancellationTokenSource();
        reader.ReadAsync(buffer, 0, BUFFER_SIZE).Wait(cTS.Token);
        string data = new string(buffer);
        if (data.IndexOf("\0") >= 0 || reader.EndOfStream)
        {
            return result + data.Substring(0, data.IndexOf("\0"));
        }
        result += data;
    }
}

我的代码适用于长度

有没有办法获取字符串的实际长度并依次读取?

reader.ReadLineAsync()

不起作用,因为字符串可以包含“\n”或“\r\n”,并且服务器不会在每个字符串的末尾添加换行符

【问题讨论】:

  • 服务器是否在每个字符串的末尾添加“\0”?
  • 不,“\0”是buffer数组中每个字符的默认值。例如,一个结果刺痛可能是: somestring\0\0\0\0\0\0
  • 那么当服务器发送长度等于4096的数据时会发生什么?缓冲区之后可能没有“\0”...但没有更多数据出现。
  • 是的,这就是为什么我需要一种方法来知道每条消息的长度或读取所有字节的时间。
  • 服务器必须告诉消息的大小。如果服务器没有提示,客户端无法猜测长度。在 TCP 之上构建的所有协议要么具有固定长度的消息,要么为传输的数据添加消息长度。例如 http 添加了Content-Length 标头。

标签: c# string sockets tcp uwp


【解决方案1】:

我终于想通了阅读长消息: 我必须使用 DataReaderDataWriter 而不是 StreamReaderStreamWriter

/// <summary>
/// How many characters should get read at once max.
/// </summary>
private static readonly int BUFFER_SIZE = 4096;

private StreamSocket socket;
private DataReader dataReader;
private DataWriter dataWriter;

public string readNextString() {
    string result = "";
    readingCTS = new CancellationTokenSource();

    try {
        uint readCount = 0;

        // Read the first batch:
        Task < uint > t = dataReader.LoadAsync(BUFFER_SIZE).AsTask();
        t.Wait(readingCTS.Token);
        readCount = t.Result;

        if (dataReader == null) {
            return result;
        }

        while (dataReader.UnconsumedBufferLength > 0) {
            result +=dataReader.ReadString(dataReader.UnconsumedBufferLength);
        }

        // If there is still data left to read, continue until a timeout occurs or a close got requested:
        while (!readingCTS.IsCancellationRequested && readCount >= BUFFER_SIZE) {
            t = dataReader.LoadAsync(BUFFER_SIZE).AsTask();
            t.Wait(100, readingCTS.Token);
            readCount = t.Result;
            while (dataReader.UnconsumedBufferLength > 0) {
                result += dataReader.ReadString(dataReader.UnconsumedBufferLength);
            }
        }
    }
    catch(AggregateException) {}
    catch(NullReferenceException) {}

    return result;
}

【讨论】:

    猜你喜欢
    • 2015-05-12
    • 2016-04-15
    • 2017-12-20
    • 2017-01-02
    • 2017-06-28
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多