【问题标题】:StreamSocket on WinRT doesn't receive all dataWinRT 上的 StreamSocket 不接收所有数据
【发布时间】:2015-03-12 21:45:22
【问题描述】:

我有一个运行 MPD(音乐播放器守护程序)的服务器,它通过套接字进行通信。现在我正在尝试在 Windows 商店应用程序中实现 MPD 协议。基本上我发送一个命令并接收一个列表,其中最后一行是“OK”。只要接收列表小于接收缓冲区,一切都可以。但是,如果我需要加载比缓冲区大的数据,那么有线的东西就会启动。

第一次调用SendCommand时我只收到部分数据,第二次调用SendCommand时收到其余数据。再次调用时,我按预期收到所有数据。在同一台机器上的 WPF 程序中执行此操作时,一切都很好。

这是我的代码:

    public async Task<string> SendCommand(MpdProtocol.MpdCommand command)
    {
        DataWriter writer = new DataWriter(streamSocket.OutputStream);
        string res = string.Empty;

        writer.WriteString(command.ToString());
        await writer.StoreAsync();
        res = await ReadResponse();

        writer.DetachBuffer();
        writer.DetachStream();
        return res;
    }

    private async Task<string> ReadResponse()
    {
        DataReader reader = new DataReader(streamSocket.InputStream);
        reader.InputStreamOptions = InputStreamOptions.Partial;
        StringBuilder response = new StringBuilder();

        const uint MAX_BUFFER = 8 * 1024;
        uint returnBuffer = 0;
        do
        {
            returnBuffer = await reader.LoadAsync(MAX_BUFFER);
            response.Append(reader.ReadString(reader.UnconsumedBufferLength));

        } while (returnBuffer >= MAX_BUFFER);

        reader.DetachBuffer();
        reader.DetachStream();

        return response.ToString();
    }

我已经使用了ReadResponse 方法,但没有任何效果。

有人能指出正确的方向吗?

【问题讨论】:

  • 我尝试了不同的方法从流中读取数据,但没有任何效果。问题是“DataReader”停止读取,但仍有数据要接收。为什么在第三次调用“SendCommand”时它会起作用?
  • 我在您的代码中看到两个明显的错误:您在写入之后和分离写入器之前没有调用writer.FlushAsync(),并且您假设对LoadAsync() 的单个调用将始终填满缓冲区除非没有更多的数据要读取。如果没有可靠地重现问题的a good, minimal, complete code example,就不可能确定您需要做什么来修复代码。但我会从那里开始。
  • (我也怀疑读者和作者的临时使用......我认为最好为每个连接创建一次并继续使用它们直到完成连接. 但是我对较新的 Windows 运行时 I/O 模型不太熟悉,也许你的代码在这方面完全没问题。我不能肯定地说)。

标签: c# .net sockets windows-runtime datareader


【解决方案1】:

最后,我找到了使通信正常工作的解决方案:使用reader.ReadByte() 逐字节读取流,并检查每条接收到的行(它们由"\n" 分隔)是否“正常”。

问题是reader.ReadString。当您知道要尝试接收的字符串有多长时,此方法很好。就我而言,我不知道字符串的大小。我所知道的是最后一行将是一个“OK”字符串。

我的错误是相信——正如彼得所说——只要有数据可以检索,接收缓冲区就会被完全填满,只有最后一次调用 reader.ReadString 会小于最大缓冲区大小。我还尝试以不同的方式重写 ReadResponse 函数,但对 reader.ReadString 没有任何效果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    • 2014-01-16
    • 2016-03-18
    • 2021-10-12
    • 1970-01-01
    相关资源
    最近更新 更多