【问题标题】:Force an async WebRequest to flush its buffer c#强制异步 WebRequest 刷新其缓冲区 c#
【发布时间】:2016-06-25 07:06:30
【问题描述】:

我有以下连接代码:

_request = (HttpWebRequest)WebRequest.Create(complianceUrl);
_request.Method = "GET";

var authInfo = string.Format("{0}:{1}", _username, _password);
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
_request.Headers.Add("Authorization", "Basic " + authInfo);

// set stream parameters
_request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
_request.Headers.Add("Accept-Encoding", "gzip");
_request.Accept = "application/json";
_request.ContentType = "application/json";
_request.ReadWriteTimeout = 30000;
_request.AllowReadStreamBuffering = false;

_request.Timeout = 30; //seconds, sends 15-second heartbeat.
_asyncCallback = HandleResult;    //Setting handleResult as Callback method...
_request.BeginGetResponse(_asyncCallback, _request);    //Calling BeginGetResponse on 

这很好用,缓冲区充满了数据,虽然我有大量数据,但这很好。但由于数据量少,缓冲区需要一段时间才能填满,如果我有一段时间没有任何活动,我想定期刷新缓冲区。

我试图这样做:

_request.GetRequestStream().FlushAsync();

但这是错误的,因为它告诉我我正在导致 ProtocolViolationException 我猜这是一个 GET 动词?

谁能告诉我如何强制导致连接将缓冲区转储到客户端?

添加处理响应代码:

private void HandleResult(IAsyncResult result)
{
    using (var response = (HttpWebResponse) _request.EndGetResponse(result))
    using (var stream = response.GetResponseStream())
    using (var memory = new MemoryStream())
    {
        var compressedBuffer = new byte[BlockSize];

        while (stream != null && stream.CanRead)
        {
            var readCount = stream.Read(compressedBuffer, 0, compressedBuffer.Length);

            // if readCount is 0, then the stream must have disconnected.  Process and abort!
            if (readCount == 0)
            {

            }
        }
    }
}

【问题讨论】:

  • 你在说什么缓冲区?我在这里看不到任何读写代码。
  • 添加了处理缓冲区的代码,但这是异步的,所以它在服务器端等到缓冲区已满,然后发送批次。我需要强制刷新连接。
  • 到底是什么问题?这段代码看起来不错。它排空流并正确检测流何时耗尽(readCount == 0)。您是在通过 HTTP 进行某种长轮询或慢速流式传输吗?
  • 异步连接,它会一直等待直到缓冲区已满,然后再刷新到客户端,这在大容量内容期间很好,但我希望能够强制连接刷新缓冲区会。
  • 那么我们可能需要查看发送数据的服务器。客户端不能导致服务器的实现进行套接字写入调用。

标签: c# asynchronous httpwebrequest flush


【解决方案1】:

不可能让 HTTP 调用的服务器端以特定方式向您发送数据。 HTTP 和 TCP 都没有这方面的规定。你必须拿走你得到的东西,或者与供应商交谈。

Read 在缓冲区满之前不会阻塞。它为您提供立即到达的内容。这种行为是众所周知的,这不是我的猜测。

第 3 方服务发送 15 秒的心跳 CRLF,最终也会填满缓冲区。

这听起来像是服务正在做你想做的事。如果这是真的,那么问题一定出在您的代码中。但不在问题中显示的代码中。试试这个:

    while (true)
    {
        var readCount = stream.Read(compressedBuffer, 0, compressedBuffer.Length);
        Console.WriteLine(readCount);
    }

这应该每 15 秒显示 2 个字节。如果不是,则供应商有过错。如果是,你就是。

while (stream != null && stream.CanRead) 这很奇怪,因为这些条件都不会变为假。即使他们变成了假的,你怎么办?!这应该是 while (true) 加上 break 流耗尽。

// if readCount is 0, then the stream must have disconnected.

此条件表示对端已经有序完成了HTTP响应的发送。

【讨论】:

  • 我添加了该代码,并将缓冲区大小设置为 10 字节。 15:48:17 读取:10BYTES 15:49:32 读取:10BYTES 如果他们每 15 秒发送一次 CRLF,我应该按照您的建议获得更多读取,当缓冲区已满时我会获取数据
  • 谢谢你,非常感谢你在这方面的帮助。我想做的事情应该很简单,我觉得这与异步连接有关
  • 流媒体似乎基本上可以工作:pastebin.com/zpZ4J6QM 如果这是 gzip 压缩的,那么您将无法再获得小块(我只是注意到)。禁用所有压缩。事实上,如果我启用压缩,那么我会得到你提到的行为。案件结案:)
  • 确认,gzip压缩不是我的朋友!!我将不得不重新考虑如何做到这一点。将此答案标记为正确!再次感谢您的帮助!
  • 以防万一您有兴趣,我让它手动压缩 gzip 流。
【解决方案2】:

对于任何感兴趣的人,您可以手动阅读和放气:

using (var response = (HttpWebResponse) _request.EndGetResponse(result))
using (var stream = response.GetResponseStream())
using (var compressedMemory = new MemoryStream())
using (var uncompressedMemory = new MemoryStream()) // Added new memory stream
using (var gzipStream = new GZipStream(compressedMemory, CompressionMode.Decompress))
{
    var compressedBuffer = new byte[BlockSize];

    while (stream != null && stream.CanRead)
    {
        var readCount = stream.Read(compressedBuffer, 0, compressedBuffer.Length);

        compressedMemory.Write(compressedBuffer.Take(readCount).ToArray(), 0, readCount);
        compressedMemory.Position = 0;

        gzipStream.CopyTo(uncompressedMemory); // use copy to rather than trying to read

        var outputString = Encoding.UTF8.GetString(uncompressedMemory.ToArray());
        Debug.WriteLine(outputString);

        uncompressedMemory.Position = 0;
        uncompressedMemory.SetLength(0);

        compressedMemory.Position = 0;
        compressedMemory.SetLength(0); // reset length
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多