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

C# 尝试在C中异步读取非结束字节流#,c#,httpwebrequest,stream,byte,httpwebresponse,C#,Httpwebrequest,Stream,Byte,Httpwebresponse,我正在连接一个服务器,该服务器发送有关财务信息的更新。我在下面发布的代码将正常工作几分钟,然后在尝试执行EndRead(我注意到的地方)时通常会爆炸,因为此时有0个字节要读取。显然,在金融界,有些东西可能会在几分钟或更长时间内保持不变的价格,这似乎是我问题的根源。此外,我怀疑有一个更好的方法来做到这一点,比我下面展示的。如果你有更有效或更优雅的方法来达到同样的效果,我洗耳恭听。基本上,我现在的代码是从这里和其他地方的随机代码片段组装而成的。我就是找不到一个能按照我需要的方式将所有部件组合在一起的

我正在连接一个服务器,该服务器发送有关财务信息的更新。我在下面发布的代码将正常工作几分钟,然后在尝试执行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;
    }
public IAsyncResult BeginStreamingData()
{
postrl=“https://”+“myfinancialbytestreamsource.com/”;
byte[]buffer=Encoding.ASCII.GetBytes(postdata);
HttpWebRequest HttpWebRequest=(HttpWebRequest)WebRequest.Create(postrl);
httpWebRequest.AutomaticDecompression=DecompressionMethods.GZip;
httpWebRequest.Method=“POST”;
httpWebRequest.ContentType=“应用程序/x-www-form-urlencoded”;
httpWebRequest.ContentLength=缓冲区.Length;
httpWebRequest.Timeout=6000000;
httpWebRequest.ReadWriteTimeout=6000000;
Stream PostData=httpWebRequest.GetRequestStream();
写(buffer,0,buffer.Length);
PostData.Close();
IAsyncResult结果=
(IAsyncResult)httpWebRequest.BeginGetResponse(新的AsyncCallback(ResponseCallback)),新的AsyncState
{
request=httpWebRequest
});
返回新的CompletedAsyncResult(“Completed stream”);
}
内部无效响应回调(IAsyncResult asynchronousResult)
{
AsyncState=asynchronousResult.AsyncState作为AsyncState;
HttpWebRequest HttpWebRequest=state.request;
state.response=(HttpWebResponse)httpWebRequest.EndGetResponse(asynchronousResult);
Stream responseStream=state.response.GetResponseStream();
字节[]缓冲区=新字节[1024*10];
var completedEvent=新手动重置事件(假);
responseStream.BeginRead(缓冲区,0,缓冲区长度,
异步读取,
新异步状态
{
b=缓冲器,
s=响应团队,
e=已完成事件
});
completedEvent.WaitOne();
}
专用void异步读取(IAsyncResult ar)
{
AsyncState=ar.AsyncState作为AsyncState;
int read=0;
//当它结束一个包含0字节的读取时,在这里爆炸(IOException)。
read=state.s.EndRead(ar);
如果(读==0)
{
//信号完成
state.e.Set();
返回;
}
其他的
{
//这就是我将字节解析为.net对象的地方。
解析字节(state.b,read);
}
//再读一遍
state.s.BeginRead(state.b,0,state.b.Length,AsyncRead,state);
}
//下面是存储状态的类。
私有类异步状态
{
公共河流;
公共事件e;
公共字节[]b;
公共HttpWebRequest请求;
公共HttpWebResponse;
}

0字节表示流已结束。APM方法不会超时,文档中明确指出,读取零是表示连接已关闭

IOException 
The stream is closed or an internal error has occurred.
流仅在流的末尾返回零(0)


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

0字节表示流已结束。APM方法不会超时,文档中明确指出,读取零是表示连接已关闭

IOException 
The stream is closed or an internal error has occurred.
流仅在流的末尾返回零(0)


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

根据文档,IOException只有在流关闭时才会抛出。因此,似乎插座连接已断开,插座已关闭

IOException 
The stream is closed or an internal error has occurred.
我建议您跟踪错误并重新打开连接


根据文档,仅当流关闭时才会引发IOException。因此,似乎插座连接已断开,插座已关闭

IOException 
The stream is closed or an internal error has occurred.
我建议您跟踪错误并重新打开连接


.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);
}

.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);
}

Http协议对于您试图实现的目标来说是错误的,每次请求后连接都会关闭。可以直接使用TCP,也可以直接轮询。

对于您试图实现的目标,Http是错误的协议,每次请求后连接都会关闭。可以直接使用TCP,也可以只进行投票。

我必须每2-3分钟进行一次投票,这对于实时金融应用程序来说是不合理的。Awe都说,当服务器关闭连接时,客户端没有什么可以做的。使用http也是一种非常奇怪的方式