2011-06-01 14 views
16

Estoy desarrollando un filtro de fuente RTSP en C++, y estoy usando WINSOCK 2.0 - socket de bloqueo.WINSOCK: ¿configura un tiempo de espera para un intento de conexión en una IP no existente?

Cuando se crea un socket de bloqueo, que establezca su SO_RCVTIMEO a 3 segundos, así:

int ReceiveTimeout = 3000; 
int e = setsockopt(Socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&ReceiveTimeout, sizeof(int)); 

Mi filtro intenta conectarse a IP_ADDRESS:554 (554 es el puerto del servidor RTSP). Si hay un servidor escuchando en ese IP en el puerto 554, todo va bien, pero:

  1. Si mi filtro crea un socket a una dirección IP existente , pero en un puerto aleatorio que nadie escucha en, connect() espera 3 segundos y devuelve WSAETIMEDOUT. Entonces, después de 3 segundos, sé que la URL proporcionada es mala.

  2. Si mi filtro crea un socket a dirección IP no existente, e intenta conectarlo, se bloquea durante aproximadamente 10 segundos antes de devolver SOCKET_ERROR. Así, SO_RCVTIMEO se tendrá en cuenta si el IP no existe en la red ...

PREGUNTA: ¿Cómo puedo configurar el tiempo de espera para una IP no existente, en el segundo caso? ¿Debo enviar ICMP PING primero para ver si existe la IP, o realizar alguna otra comprobación como esa?

Cualquier ayuda será apreciada. Gracias. :)

la respuesta a mi problema

porque estoy utilizando sockets de bloqueo, llame a connect() bloques, hasta que se establezca la conexión, o la conexión falla porque el host no responde o se niega conexión. Si establezco el tiempo de espera del socket en 3 segundos y trato de conectarme a un host que no existe, mi pc (cliente) enviará un paquete TCP con el indicador SYN establecido para iniciar el Handshake de tres vías. Normalmente, el host, si está activo, responderá con un paquete TCP que contenga los flags ACK y SYN, y luego, el cliente (me) enviará el paquete TCP con el indicador ACK establecido. Entonces la conexión está hecha. PERO si el host está inactivo y se envía el SYN, el cliente espera hasta que expire el tiempo de espera de 3 segundos y vuelve a intentar OTRA VEZ, hasta que se alcance la configuración de registro TcpMaxConnectRetransmissions (MICROSOFT ARTICLE), porque el host puede estar ARRIBA pero el SYN el paquete puede perderse ... Mi Windows XP tiene esta configuración en 4, supongo, así que cada vez que intenta enviar SYN, espera 3 segundos, y cuando la cuarta prueba falla, devuelve SOCKET_ERROR (después de 12 segundos), y establece WSAETIMEDOUT como el último error de WSA.

La forma de evitar esto es usar sockets que no sean de bloqueo e intentar medir manualmente el tiempo de intento de conexión (porque ahora el connect() no se bloquea) como sugirió Martin James.

Otra forma es que jugar con el registro, que es el último recurso ...

+0

¿Es esto en una ventana o una aplicación de consola? La pregunta es importante porque me permite saber qué herramientas en el wsapi tienes disponibles para ti. – johnathon

+0

Es un filtro DirectShow Push Source, biblioteca DLL. – Cipi

Respuesta

2

de tripas corazón. La IP remota puede no estar ejecutando un servidor PING o PING puede estar bloqueado por algún enrutador, por lo que no es de ayuda. ¿No puedes esperar los 10 segundos y luego hacer la indicación de error que usas?

Si tiene que esperar hasta el final del intento de conexión después de 3 segundos, puede hacerlo usted mismo.

+2

Recibo la captura de ping, pero ¿cómo podría cronometrarlo? ¿Cómo puedo detener el intento de conexión del socket desde otro subproceso, mientras todavía está intentando conectarse? Necesito la función 'connect()' para volver, así puedo tener un socket desconectable que funcione. ¿O estoy equivocado? – Cipi

2

En realidad, los enchufes de Berkeley no tienen tiempo de espera para conectarse, por lo que no puede configurarlo. ICMP PING no es útil, no sé por qué, pero si no existe el host, gasta alrededor de 1 segundo con PING. Intente usar ARP para detectar que el host existe.

+0

En realidad, ARP no es una opción, ya que los servidores están en WAN, no en LAN, por lo que ARP no funcionaría ... ¿o estoy equivocado? – Cipi

+0

[Wiki] (http://en.wikipedia.org/wiki/Address_Resolution_Protocol) dijo que ARP existe en IEEE 802.11 – xandox

+0

Ooook lo intentará. – Cipi

0

de cmd puede hacer ping a la IP con un tiempo de espera como esto 'ping -w 100 -n 1 192.168.1.1'

se volverá en 100 ms

puede comprobar el código de retorno 'eco % errorlevel% 0 = ok, 1 = fallan, entonces usted sabe si debe intentar conectar

en C++

bool pingip_nowait(const char* ipaddr) 
{ 
    DWORD exitCode; 

    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    ZeroMemory(&si, sizeof(si)); 
    si.cb = sizeof(si); 
    ZeroMemory(&pi, sizeof(pi)); 
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 
    si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 
    si.hStdError = GetStdHandle(STD_ERROR_HANDLE); 
    si.wShowWindow = SW_HIDE; 

    CString cmd = "ping -w 100 -n 1 "; 
    cmd += ipaddr; 
    if (!CreateProcess(NULL, 
     cmd.GetBuffer(), 
     NULL, 
     NULL, 
     FALSE, 
     0, 
     NULL, 
     NULL, 
     &si, 
     &pi)) { 
      TRACE("ERROR: Cannot launch child process\n"); 
      return false; 
    } 

    // Give the process time to execute and finish 
    WaitForSingleObject(pi.hProcess, 200L); 

    if (GetExitCodeProcess(pi.hProcess, &exitCode)) 
    { 
     TRACE("ping returned %d\n", exitCode); 
     // Close process and thread handles. 
     CloseHandle(pi.hProcess); 
     CloseHandle(pi.hThread); 
     return exitCode==0 ? true : false; 
    } 
    TRACE("GetExitCodeProcess() failed\n"); 
    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread); 
    return false; 
} 
Cuestiones relacionadas