NSURLConnectionは何度も実行されます
-
23-08-2019 - |
質問
私は各5秒のサーバと非同期に接続します。 URLは同じですが、POST-体は毎回変更されます。今、私は最初から毎回NSURL、NSURLRequestとNSURLConnectionを作成します。
私は一度接続を設定し、ちょうどさらに1ということに使用することがより効果的であると思います。 私は初心者とその可能な場合はわかりません。そこには可変NSURLConnectionはありませんが、次のようにNSURLConnectionを作成する必要がありますがあります:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
と、サーバーに別の要求を送信するためにNSMutableURLRequest POSTデータを変更します。 どっちが正しいのですか?
解決
私は、あなたが心配することはHTTP接続を作成するオーバーヘッドであると仮定します。 NSURLConnectionを使用すると、HTTP / 1.1を使用して、既存の接続を再利用するためにこれを処理するのに十分スマートです。それは私がチェックした最後の時間をパイプラインを使用しませんが、あなたの目的のために、接続の再利用は十分なはずです。私はこの上のネットワークスニファを入れて、あなたがそれらをしたいと、それが働いていることを確認することをお勧めします。
オブジェクト自体を作成するためのコストは、かつて5Sにつき、あなたは(もちろん、あなたがNSURLを再利用する必要がありますが)それを最適化しようとはならない程度の些細です。それは、特にiPhone上で、高価だサーバーへの接続を開くいます。
あなたが本当にパイプラインが必要なん見つけた場合は、、あなたは残念ながら自分自身をロールバックする必要があります。私はCFHTTPStreamがそれを行うことができますことを聞いたが、私はそれの証拠の多くが表示されません。 CocoaAsyncSocketは、低レベルのコードを記述することなく、ソケットへの低レベルアクセスのための最善の策である。
セルネットワーク上の待ち時間が非常に悪いことができますので、、それはあなたの接続が完了するまでに5秒以上かかるだろうことが可能です。 1つの接続は、次の開始前に行われている、またはあなたがより多くのオープン接続を作り始めるだろうことを確認してください。
他のヒント
物事を明確にするために、NSURLConnectionは、既存のソケットを再利用しますが、比較的小さな時間枠(12秒)のためになります。あなたがリクエストを送信する場合、応答を取り戻す、そして第二の要求が同じソケットに降ります12秒以内に次のリクエストを送信します。それ以外の場合ソケットは、クライアントによって閉じられます。バグはこのタイマーを増やすか、それが設定可能にするためにアップルに提出されました。
@Robネイピア@Ericネルソン あなたが述べたように:「NSURLConnectionを使用すると、HTTP / 1.1を使用して、既存の接続を再利用するためにこれを処理するのに十分スマートです」。 しかし、私はそれについてどのAppleの文書のような記述を見つけることができません。
の事を明確にするために、私はそれをテストするためのいくつかのコードを記述します:
- (IBAction)onClickSend:(id)sender {
[self sendOneRequest];
}
-(void)sendOneRequest {
NSURL *url = [NSURL URLWithString:@"http://192.168.1.100:1234"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
[request addValue:[Base64 encodeFromString:kValueVersion] forHTTPHeaderField:kKeyVersion];
[request addValue:[Base64 encodeFromString:kValueDataTypeCmd] forHTTPHeaderField:kKeyDataType];
[request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyCmdName];
[request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyDeviceName];
[request addValue:[Base64 encodeFromString:@"xxdafadfadfa"] forHTTPHeaderField:kKeyDTLCookies];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
そして、私は、サーバー(192.168.1.xxx)にパッケージをキャッチするのwireshark、使用を開始する「(tcp.flags.syn == 1)||(tcp.flags == 0x0010 && tcp.seq == 1 && tcp.ack == 1)」TCP 3ウェイハンドシェイクをフィルタリングします。残念ながら、私は「sendOneRequest」の各呼び出しのための3ウェイハンドシェイクを見ることができます。これは意味し、NSURLConnectionは、既存の接続を再利用していないようです。いくつかのいずれかは、私のコードで間違っているものを指摘し、どのようにNSURLConnectionずつソケット接続を介して複数のリクエストを送信することはできますか?
私はまた、リクエストを送信するための同期方法を試してみました。
-(void)sendOneRequest {
NSURL *url = [NSURL URLWithString:@"http://192.168.1.100:1234"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
[request addValue:[Base64 encodeFromString:kValueVersion] forHTTPHeaderField:kKeyVersion];
[request addValue:[Base64 encodeFromString:kValueDataTypeCmd] forHTTPHeaderField:kKeyDataType];
[request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyCmdName];
[request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyDeviceName];
[request addValue:[Base64 encodeFromString:@"xxdafadfadfa"] forHTTPHeaderField:kKeyDTLCookies];
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
sleep(1);
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
sleep(1);
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
}
そして、結果は同じである。
======= UPDATE ============================
最後に、私は私のテストは、ロブとエリック言うと異なる理由を見つけました。 要するに、ロブとエリックは正しいです。そして、NSURLConnectionはなく、比較的小さな時間枠のために、「キープアライブ」HTTP / 1.1を使用してのデフォルトとして使用し、既存のソケット接続を再利用します。
しかし、NSURLConnectionは「チャンク転送コーディング」(すなわち。コンテンツ長なし)のためのいくつかの問題があります。
は、私のテストでは、サーバー側では、コンテンツの長さとレスポンスデータのない応答を送信し、その応答をチャンクだとNSURLConnectionはそれぞれのHTTP POSTのための3ウェイハンドシェイクが発生したため、接続を閉じます。
私は、私のサーバーコードを変更0として応答の長さを設定し、動作が正しいです。
要求を返すメソッドを作成してみませんか。
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:[self requestMethod] delegate:self];