私は、Webサービスを使用していくつかのイベントをプッシュするクライアントで作業しています.Webサービスは、クライアントがサブスクライブコマンドをPOSTすると、関心のあるイベントを送り返し、クライアントは接続を維持します。
コマンドを POST すると、サービスはこれらのヘッダーを含む最初の応答で (すぐに) 応答します。
Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked
その後、タイムアウトするまで接続を開いたままにします (30 秒後、クライアントがキープアライブ データを送信しない場合)。
これは、POST + 応答を読み取る必要がある + endOFStream まで接続を開いたままにしておくことが混在しているため、HttpWebRequest を BeginGetRequestStream (POST へ) および BeginGetResponse と共に使用して、応答を読み取って処理する必要があるようです。
私の問題は、AllowReadStreamBuffering が false に設定されているにもかかわらず、入力ストリームがサーバー/サービスによって実際に閉じられるまで (30 秒後)、BeginGetResponse コールバックが呼び出されないことです。
ドキュメントには、AllowReadStreamBuffering について次のように書かれています。
AllowReadStreamBuffering プロパティは、BeginGetResponse メソッドからのコールバックが呼び出されるタイミングに影響します。AllowReadStreamBuffering プロパティが true の場合、ストリーム全体がメモリにダウンロードされると、コールバックが発生します。AllowReadStreamBuffering プロパティが false の場合、すべてのデータが到着する前に、ストリームが読み取り可能になるとすぐにコールバックが発生します。
AllowReadStreamBuffering が何に設定されていても、HttpWebRequest はバッファーがいっぱいになるまで BeginGetResponse を呼び出さないといういくつかの提案を見てきましたが、ドキュメントでそれについて何も見つけることができませんでした。
このバッファリング動作を制御する方法や、この種の Web サービスを扱うときに試してみるべき別のアプローチへの提案について、誰かが考えていますか?
私が現在使用しているコードの関連スニペットは、次のようになります。
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 :-(");
}