HttpWebRequest,BeginGetResponse直到endOfStream才被调用

时间:2013-04-08 10:50:06

标签: c# windows-phone-8

我正在使用一个使用web服务的客户端来推送一些事件 - webservice就是这样设计的,在客户端POST一个订阅命令后,它会发回一些感兴趣的事件并继续这样做只要客户保持联系。

在发布命令时,服务会立即响应这些标题的初始答案

Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked

然后保持连接打开,直到超时(30秒后,如果客户端没有发送一些保持活动数据)

由于它是POST +必须读取响应+保持连接打开直到endOFStream的混合,看来我必须使用HttpWebRequest和BeginGetRequestStream(对POST)和BeginGetResponse来读取并对响应进行操作。

我的问题是,直到服务器/服务实际关闭输入流(30秒后)才会调用BeginGetResponse回调,尽管AllowReadStreamBuffering设置为false。

文档在AllowReadStreamBuffering上有这个说法:

  

AllowReadStreamBuffering属性会影响何时调用BeginGetResponse方法的回调。当AllowReadStreamBuffering属性为true时,一旦将整个流下载到内存中,就会引发回调。当AllowReadStreamBuffering属性为false时,只要流可用于读取,就会在所有数据到达之前立即引发回调。

我已经看到一些建议,无论AllowReadStreamBuffering设置为什么,HttpWebRequest都不会调用BeginGetResponse,直到它的缓冲区被填满 - 但我无法在文档中找到任何内容。

有没有人知道如何控制这种缓冲行为,或者建议我在处理这种网络服务时应该尝试另一种方法?

我目前使用的代码的相关片段如下所示:

public void open()
{
    string url = "http://funplaceontheinternet/webservice";

    HttpWebRequest request = WebRequest.CreateHttp(url);
    request.Method = "POST";
    request.Credentials = new NetworkCredential("username", "password");
    request.CookieContainer = new CookieContainer();
    request.AllowReadStreamBuffering = false;         
    request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}

void GetRequestStreamCallback(IAsyncResult result)
{
    Debug.WriteLine("open.GetRequestStreamCallback");

    HttpWebRequest webRequest = (HttpWebRequest)result.AsyncState;
    // End the stream request operation
    Stream postStream = webRequest.EndGetRequestStream(result);

    // Create the post data
    byte[] byteArray = Encoding.UTF8.GetBytes(_xmlEncodedSubscribeCommand);

    // Add the post data to the web request
    postStream.Write(byteArray, 0, byteArray.Length);
    postStream.Close();

    // Start the web request
    webRequest.BeginGetResponse(new AsyncCallback(BeginGetResponseCallback), webRequest);
}

void BeginGetResponseCallback(IAsyncResult result)
{
    HttpWebRequest request = (HttpWebRequest)result.AsyncState;
    HttpWebResponse response = null;
    if (request != null)
        response = (HttpWebResponse)request.EndGetResponse(result);
    else
        Debug.WriteLine("request==null :-(");
    if (response != null)
    {
        using (var reader = new StreamReader(response.GetResponseStream()))
        {
            while (!reader.EndOfStream)
            {
                string line = reader.ReadLine();
                Debug.WriteLine("BeginGetResponseCallback - received: " + line);
            }
            Debug.WriteLine("BeginGetResponseCallback - reader.EndOfStream");
        }
    }
    else
        Debug.WriteLine("response==null :-(");
}

1 个答案:

答案 0 :(得分:0)

您已经提到该服务是一项Web服务,但不是哪个平台。 如果这是"正常" Web服务,然后我假设XML是传输格式。

如果是这样,我怀疑问题可能是这种沟通方式并不真正适合流式传输。在所有数据都可用之前,服务器端的Web服务基础结构可能不会创建SOAP信封和有效负载。如果你想像这样流,你最好在服务器端使用一些自定义服务,而不是Web服务。

您是否确定服务器确实正在流式传输响应? (例如用wireshark之​​类的东西确认?)

如果您真的想使用网络服务,那么我会建议您在第一个活动可用时完成请求,并且不要等待超时。这仍将实现我假设你想要的延迟减少。