2011-01-17 11 views
6

Usando .Net 4.0. Tengo un código que intenta abrir una conexión usando BeginConnect y una devolución de llamada. Si el usuario intenta detener la programación en los próximos momentos, intento desconectarme. En ese punto, establecí una bandera para indicar si el EndConnect necesita ser llamado desde la devolución de llamada. Si el indicador se establece en falso, omito EndConnect porque el socket se ha descartado de todos modos.¿Qué sucede si nunca llamas a Socket.EndConnect?

En este punto, el usuario puede intentar conectarse de nuevo inmediatamente. No veo que esto ocurra, pero por las dudas. Ahora se crea un nuevo socket y se llama nuevamente a BeginConnect.

¿Está bien nunca llamar al método EndConnect?

Respuesta

3

En todos los casos (excepto uno [1]) una llamada a BeginZZZ necesita un EndZZZZ a juego.

De lo contrario, los recursos no administrados se van a filtrar, y es muy posible que la acción ZZZZ no complete correctamente — y pueda dañar otros usos posteriores de ZZZZ.

Los zócalos son bastante robustos contra el abuso (la pila IP tiene que manejar fallas de red y paquetes desordenados), pero eso no lo convierte en una buena práctica.

Si está utilizando un indicador para rastrear "apagar", mejor llamar al EndConnect y luego cierre el socket inmediatamente. Después de todo, la conexión podría fallar y no se necesita una desconexión (EndConnect arroja SocketException). Algo como:

mySocket.BeginConnect(address, port, ia => { 
    if (shuttingDown) { 
    try { 
     mySocket.EndConnect(ia); 
     mySocket.BeginDisconnect(false, iaa = { 
     try { 
      mySocket.EndDisconnect(iaa); 
     } catch (Exception) { /* Ignore */ } 
     }, null); 
    } catch (SocketException) { /* Ignore */ } 
    } else { 
    // Normal connection handling 
    } 
}, null); 

También utilizando la desconexión asincrónica para evitar el bloqueo allí.


[1] La excepción es Control.BeginInvoke en WinForms, donde la excepción se documenta explícitamente.

+0

@Richard. Gracias por la respuesta. Intenté su enfoque, pero sigo recibiendo excepciones sobre que AsyncResult no sea el mismo desde la llamada de inicio correspondiente. Me encontré con el blog de un tipo que dice que deberíamos guardar en caché el AsyncResult y comprobar si es el mismo antes de hacer cualquier cosa. Esto parece dudoso y me deja de nuevo en el punto de partida de todos modos. Simplemente ignorando la cosa. – uriDium

+0

@Richard. Bien, guau. El MSDN es muy débil en un par de cosas. Primero dice: Puede crear un método de devolución de llamada que implementa el delegado AsyncCallback y pasar su nombre al método BeginConnect. Lo que realmente suena como que es opcional. Luego, los siguientes párrafos indican: su método de devolución de llamada debe invocar el método EndConnect. Me acaban de decir que es opcional ahora que me dicen que debo llamar a EndConnect. No puedo llamar a EndConnect si lo dejo "opcionalmente". Sin embargo: Esta parte me dio esperanza: para cancelar una llamada pendiente al método BeginConnect, cierre el Socket. – uriDium

+0

@uriDium: la devolución de llamada es opcional, pero la llamada 'EndConnect' no lo es. En su lugar, puede esperar el 'IAsyncResult' devuelto por' BeginConnect' (o sondear su propiedad 'IsCompleted') y luego llamar a' EndConnect', todo sin usar la devolución de llamada. Resumen: debe llamarse a 'EndConnect', pero no es necesario que esté dentro del delegado pasado a 'BeginConnect'. – Richard

Cuestiones relacionadas