visual socket example dev c++ winsock2

c++ - socket - winsock windows



WINSOCK: ¿está configurando un tiempo de espera para un intento de conexión en una IP no existente? (3)

Estoy desarrollando un filtro de fuente RTSP en C ++, y estoy usando WINSOCK 2.0 - zócalo de bloqueo.

Cuando creo un socket de bloqueo, configuro su SO_RCVTIMEO en 3 segundos como SO_RCVTIMEO :

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 esa IP en el puerto 554, todo va bien, pero:

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

  2. Si mi filtro crea un socket a una dirección IP no existente e intenta conectarlo, se cuelga durante unos 10 segundos antes de devolver SOCKET_ERROR. Entonces, SO_RCVTIMEO se ignora si la 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 verificación como esa?

Cualquier ayuda será apreciada. Gracias :)

LA RESPUESTA A MI PROBLEMA

Debido a que estoy usando sockets de bloqueo, llame a los bloques connect() , hasta que se realice la conexión, o la conexión falle porque el host no responde, o se niega la conexión. Si configuro el tiempo de espera del socket en 3 segundos e intento conectarme a un host que no existe, mi PC (cliente) enviará un paquete TCP con el conjunto de indicadores SYN para iniciar el protocolo de enlace de Threeway . Normalmente, el host, si está activado, responderá con el paquete TCP que contiene los indicadores ACK y SYN establecidos, y luego, el cliente (yo) enviará el paquete TCP con el conjunto de indicadores ACK . Entonces se hace la conexión. PERO si el host está inactivo, y se envía el SYN , el cliente espera hasta que el tiempo de espera de 3 segundos expire, y luego intente de nuevo, y OTRA VEZ, hasta que se TcpMaxConnectRetransmissions la TcpMaxConnectRetransmissions del TcpMaxConnectRetransmissions ( MICROSOFT ARTICLE ), porque el host puede estar UP pero el SYN paquete SYN podría perderse ... Mi Windows XP tiene esta configuración en 4, supongo, por lo que cada vez que intenta enviar SYN , espera 3 segundos, y cuando el cuarto intento 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 no bloqueadores e intentar medir manualmente el tiempo de intento de conexión (porque ahora no se bloquearía el conector connect() ) como sugirió Martin James.

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


En realidad, los zócalos de Berkeley no tienen tiempo de espera para la conexión, por lo que no puede configurarlo. ICMP PING no es útil, no sé por qué, pero si no existe un host, gasta alrededor de 1 segundo con PING. Trate de usar ARP para detectar si el host existe.


Morder la bala. Es posible que la IP remota no esté ejecutando un servidor PING o que algún enrutador pueda bloquear PING, por lo que no sirve de ayuda. ¿No puedes simplemente esperar 10 segundos y luego hacer cualquier indicación de error que uses?

Si absolutamente tiene que suspender el intento de conexión después de 3 segundos, puede hacerlo usted mismo.


desde cmd puede hacer ping a la ip con un tiempo de espera como este ''ping -w 100 -n 1 192.168.1.1''

volverá dentro de 100mS

puede verificar el código de retorno por ''echo% errorlevel% 0 = ok, 1 = fail, entonces sabrá si debe intentar conectarse

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