4

我正在开发一个客户端,该客户端使用网络服务来获取一些事件推送 - 网络服务的设计是这样的,在客户端发布订阅命令时,它会发回一些感兴趣的事件并继续这样做,只要客户端保持连接。

发布命令时,服务会(立即)以带有这些标头的初始答案进行响应

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

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

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

我的问题是 BeginGetResponse 回调直到输入流被服务器/服务实际关闭(30 秒后)才被调用,尽管 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 :-(");
}
4

1 回答 1

0

您已经提到该服务是 Web 服务,但不是哪个平台。如果这是一个“正常”的 Web 服务,那么我假设 XML 是传输格式。

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

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

如果您真的想使用 Web 服务,那么我建议您在第一个事件可用时完成请求,并且不要等待超时。这仍将实现我假设您尝试获得的延迟减少。

于 2013-07-13T09:09:16.977 回答