@Rob Napier @Eric Nelson Como mencionaste: "NSURLConnection es lo suficientemente inteligente como para manejar esto usando HTTP/1.1 y reutilizando las conexiones existentes". Sin embargo, no puedo encontrar tal descripción en ningún documento de Apple al respecto.
Para hacer algo en claro, que escribir código para probarlo:
- (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];
}
Y entonces, comienzo Wireshark para capturar paquetes en el servidor (192.168.1.xxx), usando "(tcp.flags .syn == 1) || (tcp.flags == 0x0010 & & tcp.seq == 1 & & tcp.ack == 1) "para filtrar tcp agitador manual de 3 vías. Desafortunadamente, puedo ver el movimiento de manos de 3 vías para cada llamada de "sendOneRequest". Lo que significa que el NSURLConnection parece no reutilizar las conexiones existentes. ¿Puede alguien señalar lo que está mal en mi código y cómo enviar solicitudes múltiples a través de una conexión de socket mediante NSURLConnection?
También probé manera sincrónica a enviar solicitud:
-(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];
}
y el resultado es el mismo.
======= ACTUALIZACIÓN ============================
Por último, he encontrado la razón por qué mi prueba es diferente de Rob y Eric dicen. En resumen, Rob y Eric están en lo cierto. Y NSURLConnection usa "keep-alive" como predeterminado para usar HTTP/1.1 y reutiliza la conexión de socket existente, pero solo para un marco de tiempo relativamente pequeño.
Sin embargo, NSURLConnection tiene algunos problemas para la "codificación de transferencia fragmentada" (es decir, sin contenido de longitud).
En mi prueba, el lado del servidor envía una respuesta sin contenido de longitud y datos de respuesta, y su respuesta fragmentada y NSURLConnection cerrará la conexión, por lo que se producirá agitación tridireccional de las manos para cada publicación HTTP.
Cambié el código de mi servidor, establecí la duración de la respuesta en 0 y el comportamiento es correcto.
if (! Conexión) connection = [[NSURLConnection alloc] initWithRequest: request delegate: self startImmediately: NO]; [inicio de la conexión]; Este no funciona, da "EXC_BAD_ACCESS". Busqué foros para eso y no hay respuesta. Parece que 'inicio' es necesario para usar de otra manera. – slatvick
Es una rareza de este método de inicialización que debe programar la conexión en un runloop antes de iniciarlo. –