强制异步 WebRequest 刷新其缓冲区 c#
Force an async WebRequest to flush its buffer c#
我有以下连接代码:
_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
这很好用,缓冲区充满了数据,虽然我有大量数据,但这很好。但是由于数据量小,缓冲区需要一段时间才能填满,如果我有一段时间没有 activity,我想定期刷新缓冲区。
我试过这样做:
_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)
{
}
}
}
}
无法使 HTTP 调用的服务器端以特定方式向您发送数据。 HTTP 和 TCP 都没有这方面的规定。你必须拿走你得到的东西,或者与供应商交谈。
Read
在缓冲区满之前不会阻塞。它给你立即到达的东西。这种行为是众所周知的,这不是我的猜测。
The 3rd party service send 15 second heartbeats CRLF which will also eventually fill up the buffer.
这听起来像是服务正在做您想要的。如果是这样,则问题一定出在您的代码中。但不在问题中显示的代码中。试试这个:
while (true)
{
var readCount = stream.Read(compressedBuffer, 0, compressedBuffer.Length);
Console.WriteLine(readCount);
}
这应该每 15 秒显示 2 个字节。如果不是,则供应商有过错。如果是,那你就是。
while (stream != null && stream.CanRead)
这很奇怪,因为 none 这些条件可能变为假。即使它们变成假的,你会怎么做?!这应该是 while (true)
加上流耗尽时的 break
。
// if readCount is 0, then the stream must have disconnected.
这种情况意味着远程端已经有序地完成了 HTTP 响应的发送。
对于任何感兴趣的人,您可以阅读并手动执行以下操作:
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
}
}
我有以下连接代码:
_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
这很好用,缓冲区充满了数据,虽然我有大量数据,但这很好。但是由于数据量小,缓冲区需要一段时间才能填满,如果我有一段时间没有 activity,我想定期刷新缓冲区。
我试过这样做:
_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)
{
}
}
}
}
无法使 HTTP 调用的服务器端以特定方式向您发送数据。 HTTP 和 TCP 都没有这方面的规定。你必须拿走你得到的东西,或者与供应商交谈。
Read
在缓冲区满之前不会阻塞。它给你立即到达的东西。这种行为是众所周知的,这不是我的猜测。
The 3rd party service send 15 second heartbeats CRLF which will also eventually fill up the buffer.
这听起来像是服务正在做您想要的。如果是这样,则问题一定出在您的代码中。但不在问题中显示的代码中。试试这个:
while (true)
{
var readCount = stream.Read(compressedBuffer, 0, compressedBuffer.Length);
Console.WriteLine(readCount);
}
这应该每 15 秒显示 2 个字节。如果不是,则供应商有过错。如果是,那你就是。
while (stream != null && stream.CanRead)
这很奇怪,因为 none 这些条件可能变为假。即使它们变成假的,你会怎么做?!这应该是 while (true)
加上流耗尽时的 break
。
// if readCount is 0, then the stream must have disconnected.
这种情况意味着远程端已经有序地完成了 HTTP 响应的发送。
对于任何感兴趣的人,您可以阅读并手动执行以下操作:
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
}
}