sockets - number - tcp socket c++
¿Cómo obtengo un puerto de socket libre? C++ (6)
Creo que es mejor elegir un puerto fijo en lugar de depender del número de puerto aleatorio elegido por el O / S.
Si usa un puerto aleatorio, deberá cambiar la configuración de su firewall cada vez que ejecute el programa.
Estoy escribiendo un cliente / servidor de prueba UDP y quiero obtenerlo a través del firewall. Supuestamente, todo lo que tengo que hacer es enviar ambas partes a la IP y el servidor correctos. Obtener una IP no es un problema, pero ¿cómo hago para que el cliente elija un puerto libre aleatorio y se lo informe al usuario? Eventualmente querría que se conectara con un servidor de emparejamiento pero ahora mismo necesito un prototipo simple de trabajo y me gustaría citar el número de puerto para que mi amigo / probador pueda enviarme el # por mensajería instantánea para que podamos probarlo.
¿Cómo obtengo el número de puerto? perdón por el largo desc. Noto que la gente me dice que no haga lo que estoy pidiendo cuando no doy un desc :(
En general, usted, como desarrollador, elige el puerto. Puede configurar su aplicación para que lea el puerto desde un archivo de configuración o la entrada del usuario, pero ningún firewall mágico le dirá qué puerto usar ...
Si entiendo tu pregunta correctamente, no estoy seguro de que haya una manera de hacer lo que deseas programáticamente (y aunque exista, no creo que sea el enfoque correcto). Creo que debe encontrar un puerto que no esté en uso en la máquina del servidor (y quizás 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 cortafuegos . Supongo que como dices "obtener una IP no es un problema", ¿ya has configurado tu 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 ejecute 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 que ese. Puede usar una herramienta simple de escaneo de puertos como nmap para ver qué servicios se están ejecutando en su computadora en qué puertos y elegir uno diferente. Tenga en cuenta que nmap
puede ser engañado por firewalls y varias reglas de vinculación cuando se crean sockets.
Si está utilizando WINSOCK, consulte este enlace: http://msdn.microsoft.com/en-us/library/aa280717(VS.60).aspx Básicamente tiene 2 opciones para configurar el puerto en 0 y dejar que el sistema le asigne uno o elige uno al azar intente abrir el zócalo si no funciona intente con otro (asegúrese de mantenerse alejado de los puertos reservados)
Para utilizar el término altamente técnico, este es realmente un problema bastante asqueroso o incluso un par de problemas repulsivos. Dependiendo de la configuración del firewall, generalmente permitirá respuestas desde otro punto final en el punto final IP a medida que la solicitud provenga. Entonces ... si su amigo recibe el datagrama UDP usando algo como la llamada al sistema recvfrom()
, el parámetro de dirección recibirá la información del punto final IP a la que responder. Entonces, el otro extremo debería poder responder con sendto()
usando 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 externa 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 debería enviar datos. En última instancia, puede no importar qué puerto elijas usar, ya que el firewall podría estar enviando y recibiendo en un puerto completamente diferente: de esto se trata la Traducción de direcciones de red . Yo recomendaría leer RFC3235 para algunos consejos sobre cómo superar ese obstáculo.
El mejor enfoque en mi humilde opinión es:
- Deje que el sistema operativo elija un puerto llamando a
bind()
con un número de puerto cero u omitiendo el enlace por completo - Hacer que el cliente reciba la información de la dirección de la capa de socket (por ejemplo, el quinto y sexto argumentos para
recvfrom()
) - El cliente envía una respuesta al punto final recuperado en el paso anterior
- Ajustar las configuraciones del firewall hasta que los pasos anteriores funcionen
Por supuesto, toda la magia está en el último paso. Si puede deshabilitar NAT o asegurarse de que el firewall nunca va a cambiar de puerto, entonces también funcionará clavar un número de puerto y bind
. Es posible que desee echar un vistazo a %WINDIR%/system32/drivers/etc/services
(o /etc/services
dependiendo de la inclinación de su sistema operativo) para tener una idea de los números de puerto reservados o generalmente en uso.
bind () el socket antes de enviar sus datos. Especifique el puerto 0 para bind (), y el sistema operativo elegirá un puerto no utilizado para usted. Luego puede usar getsockname () para averiguar qué puerto eligió wsa.