Question

je connecte de manière asynchrone avec le serveur toutes les 5 secondes. L'URL est le même, mais POST-corps est changé chaque fois. Maintenant, je crée NSURL, NSURLRequest et NSURLConnection à partir de zéro à chaque fois.

Je pense qu'il serait plus efficace de mettre en connexion une fois et il suffit d'utiliser un autre que. Je suis un débutant et ne savez pas si cela est possible. Il n'y a pas mutable NSURLConnection, mais il est peut-être créer NSURLConnection comme:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

et modifier NSMutableURLRequest POST-données pour envoyer une autre requête au serveur. De quel côté est la bonne?

Était-ce utile?

La solution

Je suppose que ce que vous êtes préoccupé par est la surcharge de la création de la connexion HTTP. NSURLConnection est assez intelligent pour gérer cela pour vous en utilisant HTTP / 1.1 et réutiliser les connexions existantes. Il n'utilise pipelining dernière fois que je vérifié, mais votre but, la réutilisation de connexion devrait être suffisante. Je vous encourage à mettre un renifleur à ce sujet et assurez-vous qu'il fonctionne en tant que réseau que vous voulez.

Le coût de la création des objets eux-mêmes est trivial de l'ordre d'une fois par 5 secondes et vous ne devriez pas essayer d'optimiser ce que (même si bien sûr vous devez réutiliser le NSURL). Il est l'ouverture d'une connexion au serveur qui est cher, en particulier sur l'iPhone.

Si vous vous trouvez vraiment besoin pipelining, vous devrez malheureusement rouler votre propre. Je l'ai entendu dire que CFHTTPStream peut le faire, mais je ne vois pas beaucoup de preuves de cela. CocoaAsyncSocket est votre meilleur pari pour un accès bas niveau aux prises sans avoir à écrire du code de bas niveau.

Depuis la latence sur le réseau cellulaire peut être très mauvais, il est possible que votre connexion prendra plus de 5 s à compléter. N'assurez-vous qu'une connexion est faite avant de commencer la suivante, ou vous allez commencer à faire des connexions de plus en plus ouvertes.

Autres conseils

Juste pour clarifier les choses, NSURLConnection réutilisera prises existantes, mais seulement pour un laps de temps relativement faible (12 secondes). Si vous envoyez une demande, retourner une réponse, et envoyer une demande ultérieure dans les 12 secondes qui demande 2 sera sorti sur le même socket. Sinon, la prise sera fermée par le client. Un bug a été déposé avec Apple pour augmenter cette minuterie ou pour le rendre configurable.

@Rob Napier @Eric Nelson Comme vous l'avez mentionné: « NSURLConnection est assez intelligent pour gérer cela pour vous en utilisant HTTP / 1.1 et réutiliser les connexions existantes ». Cependant, je ne trouve pas cette description dans le document tout d'Apple à ce sujet.

Pour rendre les choses claires, j'écrire du code pour le tester:

- (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];
}

Et puis, je commence Wireshark pour attraper des paquets sur le serveur (192.168.1.xxx), en utilisant « (tcp.flags.syn == 1) || (tcp.flags == 0x0010 && tcp.seq == 1 && tcp.ack == 1) » pour filtrer tcp 3 voies serrer la main. Malheureusement, je peux voir la poignée de main à 3 voies pour chaque appel de « sendOneRequest ». Ce qui signifie, le NSURLConnection semble pas réutiliser les connexions existantes. Quelqu'un peut indiquer ce qui ne va pas dans mon code et comment envoyer plusieurs demandes via une connexion socket par NSURLConnection?

J'ai aussi essayé de façon synchrone d'envoyer la demande:

-(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];

}

Et le résultat est le même.

======= MISE À JOUR ============================

Enfin, j'ai trouvé la raison pour laquelle mon test est différent de Rob et Eric disent. En bref, Rob et Eric sont corrects. Et NSURLConnection utilise « keep-alive » par défaut pour l'utilisation de HTTP / 1.1 et réutilise connexion socket existante, mais seulement pour un laps de temps relativement faible.

Cependant, NSURLConnection a quelques problèmes pour « codage de transfert mémorisé en bloc » (ie. Sans-longueur du contenu).

Dans mon test, côté serveur envoyer une réponse sans longueur du contenu et des données de réponse, et il est la réponse chunked et NSURLConnection fermera la connexion, ainsi 3 voies de poignée de main se produit pour chaque poste http.

J'ai changé mon code serveur, définissez la longueur de la réponse 0, et le comportement est correct.

faire une méthode qui renvoie une demande et faire

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:[self requestMethod] delegate:self];

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top