试图在C#中异步读取非结束字节流

时间:2010-10-13 22:44:53

标签: c# httpwebrequest stream byte httpwebresponse

我正在连接到发送有关财务信息的更新的服务器。我在下面发布的代码将正常工作几分钟,然后在尝试执行EndRead(我已经注意到)时通常会爆炸,因为此时有0个字节需要读取。显然在金融界,有些东西可以保持相同的价格几分钟或更长时间,这似乎是我的问题的根源。另外我怀疑有一种比我在下面展示的更好的方法。如果你有一个更有效或更优雅的方式来实现相同的结果,我很满意。基本上我现在的代码是从这里和其他地方的随机代码片段汇编而成的。我似乎无法找到一个将所有碎片放在一起的样本。

提前致谢,

鲍勃

编辑:我应该澄清一下,我基本上了解出了什么问题,我只是找不到流被关闭的原因。我认为最好的答案将是一个不同的实现,它做同样的事情。我尝试让WebClient做到这一点,但没有任何运气。

public IAsyncResult BeginStreamingData()
    {
        postUrl = "https://" + "myfinancialbytestreamsource.com/";
        byte[] buffer = Encoding.ASCII.GetBytes(postdata);
        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(postUrl);
        httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip;
        httpWebRequest.Method = "POST";
        httpWebRequest.ContentType = "application/x-www-form-urlencoded";
        httpWebRequest.ContentLength = buffer.Length;
        httpWebRequest.Timeout = 6000000;
        httpWebRequest.ReadWriteTimeout = 6000000;
        Stream PostData = httpWebRequest.GetRequestStream();
        PostData.Write(buffer, 0, buffer.Length);
        PostData.Close();

        IAsyncResult result =
          (IAsyncResult)httpWebRequest.BeginGetResponse(new AsyncCallback(ResponseCallback), new AsyncState
          {
              request = httpWebRequest
          });

        return new CompletedAsyncResult<string>("Completed stream.");
    }

internal void ResponseCallback(IAsyncResult asynchronousResult)
    {
        AsyncState state = asynchronousResult.AsyncState as AsyncState;
        HttpWebRequest httpWebRequest = state.request;
        state.response = (HttpWebResponse)httpWebRequest.EndGetResponse(asynchronousResult);

        Stream responseStream = state.response.GetResponseStream();
    byte[] buffer = new byte[1024 * 10];

    var completedEvent = new ManualResetEvent(false);

    responseStream.BeginRead(buffer, 0, buffer.Length,
                            AsyncRead,
                            new AsyncState
                            {
                                b = buffer,
                                s = responseStream,
                                e = completedEvent
                            });

    completedEvent.WaitOne();
    }

private void AsyncRead(IAsyncResult ar)
    {
        AsyncState state = ar.AsyncState as AsyncState;
        int read = 0;

//BLOWS UP HERE (IOException) WHEN IT ENDS A READ THAT HAD 0 BYTES IN IT.

read = state.s.EndRead(ar);

            if (read == 0)
            {
                // signal completion
                state.e.Set();
                return;
            }
            else
            {
                //this is where I'm parsing the bytes into .net objects.
                ParseBytes(state.b, read);

            }
            // read again
            state.s.BeginRead(state.b, 0, state.b.Length, AsyncRead, state);
    }

//Here is the class that stores the state.
private class AsyncState
    {
        public Stream s;
        public ManualResetEvent e;
        public byte[] b;
        public HttpWebRequest request;
        public HttpWebResponse response;
    }

4 个答案:

答案 0 :(得分:0)

0字节表示流已结束。 APM方法不会超时,并且文档清楚地指出读取零个字节表示连接已关闭。

  

Streams仅在流的末尾返回零(0)

您确定要在正确的位置进行故障排除吗? IOException几乎肯定包含更多有用的信息。

答案 1 :(得分:0)

根据文档,仅在关闭流时抛出IOException。因此看起来套接字连接已断开且套接字已关闭。

IOException 
The stream is closed or an internal error has occurred.

我建议您跟踪错误并重新打开连接。

http://msdn.microsoft.com/en-us/library/system.io.stream.endread.aspx

答案 2 :(得分:0)

.NET Framework 4 / 4.5具有内置的优化异步HttpClient类。您可以使用它们来实现几乎所有您想要的HTTP。

var responseMessage = await (new HttpClient().GetAsync("http://download.linnrecords.com/test/flac/recit24bit.aspx", HttpCompletionOption.ResponseHeadersRead));
if (responseMessage.StatusCode == System.Net.HttpStatusCode.OK)
{
    var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test_http_download.flac");
    using (var fileStream = File.Create(filePath))
    using (var httpStream = await responseMessage.Content.ReadAsStreamAsync())
    {
        httpStream.CopyTo(fileStream);
        fileStream.Flush();
    }
    Process.Start(filePath);
}

答案 3 :(得分:0)

Http是您尝试实现的错误协议,在每次请求后关闭连接。直接使用TCP或只是轮询。