Pregunta

Estoy escribiendo un cliente / servidor de prueba UDP y quiero hacerlo a través del firewall. Supuestamente, todo lo que debo hacer es que ambos lados se envíen al IP y al servidor correctos. Obtener una IP no es un problema, pero ¿cómo puedo hacer que el cliente elija un puerto libre aleatorio y lo informe al usuario? Eventualmente querría que se conecte a un servidor de Matchmaker, pero ahora mismo necesito un prototipo simple y me gustaría descifrar el número de puerto para que mi amigo / probador pueda enviarme el # vía IM para que podamos probar.

¿Cómo obtengo el número de puerto? perdon por el largo desc. Me doy cuenta de que la gente me dice que no haga lo que estoy pidiendo cuando no doy un desc :(

¿Fue útil?

Solución

Para usar el término altamente técnico, este es en realidad un problema bastante complicado o incluso un par de problemas difíciles. Dependiendo de la configuración del firewall, por lo general, permitirá respuestas de otro punto final en el punto final de IP de donde proviene la solicitud. Entonces ... si su amigo recibe el datagrama UDP utilizando algo como la llamada al sistema recvfrom () , el parámetro de dirección recibirá la información del punto final de IP para responder. Por lo tanto, el otro extremo debe poder responder con un send to () utilizando la misma información de direccionamiento. Algo como:

/* initiator */
struct sockaddr_in hisaddr;
memset(&hisaddr, 0, sizeof(hisaddr));
hisaddr.sin_addr.s_addr = htonl(target_ip);
hisaddr.sin_port = htons(target_port);
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&hisaddr, sizeof(hisaddr));

/* receiver */
struct sockaddr_in peeraddr;
socklen_t peer_sz = sizeof(peeraddr);
recvfrom(sd, buf_ptr, buf_sz, 0, (struct sockaddr*)&peeraddr, &peer_sz);
/* build response */
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&peeraddr, peer_sz);

El peeraddr en el otro lado será su dirección external o, más correctamente, la dirección IP de su firewall y el número de puerto que eligió usar. El número de puerto que especifique en su código puede ser completamente diferente al puerto al que su amigo tendría que enviar datos. En última instancia, puede que no importe el puerto que elija usar, ya que el firewall podría estar enviando y recibiendo en un puerto completamente diferente. Esto es lo que La traducción de direcciones de red se trata. Recomendaría leer RFC3235 para obtener algunos consejos sobre cómo superar ese obstáculo.

El mejor enfoque en mi humilde opinión es:

  1. Deje que el sistema operativo elija un puerto ya sea llamando a bind () con un número de puerto cero u omitiendo el enlace por completo
  2. Hacer que el cliente reciba la información de dirección de la capa de socket (por ejemplo, los argumentos quinto y sexto a recvfrom () )
  3. El cliente envía una respuesta al punto final recuperado en el paso anterior
  4. Modifique las configuraciones del firewall hasta que funcionen los pasos anteriores

Por supuesto, toda la magia está en el último paso. Si puedes desactivar NAT o asegurarte de que el firewall nunca cambiará de puerto, entonces el establecimiento de un número de puerto y el bind también funcionarán. Es posible que desee consultar % WINDIR% \ system32 \ drivers \ etc \ services (o / etc / services según la inclinación de su sistema operativo) para tener una idea de qué números de puerto están reservados o generalmente en uso.

Otros consejos

En términos generales, usted, como desarrollador, elige el puerto. Puede configurar su aplicación para que lea el puerto desde un archivo de configuración o entrada del usuario, pero ningún firewall mágico le dirá qué puerto usar ...

Si entiendo su pregunta correctamente, no estoy seguro de que haya una manera de hacer lo que quiere programáticamente (e incluso si lo hay, no creo que sea el enfoque correcto). Creo que necesita encontrar un puerto que no esté en uso en la máquina del servidor (y tal vez un puerto diferente o el mismo en la máquina cliente, si la comunicación es bidireccional) Y ese puerto debe poder pasar a través de su firewall . Supongo que ya que dice "obtener un IP no es un problema", ¿ya configuró su firewall para reenviar algunos o todos los puertos a una computadora específica dentro del firewall? Si es así, el puerto que busca es uno de los que reenvió. Solo puede elegir uno arbitrario, siempre que no se esté ejecutando ningún otro servicio en ese puerto. Los puertos por debajo de 1024 están reservados, por lo que es probable que desee elegir un número mayor. Puede usar una herramienta de exploración de puertos simple como nmap para ver qué servicios se están ejecutando en su computadora en qué puertos y elegir un diferente uno. Tenga en cuenta que nmap puede ser engañado por los firewalls y varias reglas de bind cuando se crean sockets.

Creo que es mejor elegir un puerto fijo en lugar de confiar en el número de puerto aleatorio elegido por el O / S.

Si usa un puerto aleatorio, tendrá que cambiar la configuración de su firewall cada vez que ejecute el programa.

Si está utilizando WINSOCK, verifique este enlace: http://msdn.microsoft.com/en-us /library/aa280717(VS.60).aspx Básicamente, tiene 2 opciones: configure el puerto en 0 y deje que el sistema le asigne una o elija una aleatoria. Intente abrir el socket si no funciona. Pruebe otra (asegúrese de mantenerse alejado de los puertos reservados)

vincule () el socket antes de enviar sus datos. Especifique el puerto 0 para enlazar (), y el sistema operativo elegirá un puerto no utilizado para usted. Luego, puede usar getsockname () para averiguar qué puerto se eligió.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top