2009-07-02 16 views
38

Necesito una aplicación que envíe un paquete UDP a algún servidor de red y reciba la respuesta. El servidor responde al mismo número de puerto de donde vino la solicitud, así que primero necesito vincular() mi socket a cualquier número de puerto UDP.¿Cómo enlazar a un puerto disponible?

La codificación rígida del número de puerto UDP es una mala idea, ya que podría ser utilizada por cualquier otra aplicación que se ejecute en la misma PC.

¿Hay alguna manera de vincular un socket UDP a cualquier puerto disponible? OMI debe ser una forma efectiva de obtener rápidamente un número de puerto libre, que se utiliza, por ejemplo, la función accept().

Si no, ¿cuál es la mejor estrategia para intentar vincular y comprobar el estado de WSAEADDRINUSE/EADDRINUSE: pruebe los puertos secuencialmente a partir de 1025, o 1025 + rand(), o de algún otro modo?

+1

accept() se usa en conectores basados ​​en conexión, no en datagramas. – Beano

+1

quizás esto ayude: http://serverfault.com/questions/447044 – yegor256

+0

¿En POSIX? También requiere un rango 1024+: http://stackoverflow.com/questions/913501/how-to-let-kernel-choose-a-port-number-in-the-range-1024-5000-in-tcp-socket- pr –

Respuesta

34

Llamada sendto sin llamar primero a bind, el socket se vinculará automáticamente (a un puerto libre).

+5

Downvoting solo porque la respuesta correcta debe ser la de @ Remy (usando el puerto 0 en el enlace). – claf

+4

@claf bind implícito también es bind, ¿no? Ambas respuestas son útiles, en mi opinión. – WGH

+0

@WGH: tiene razón, este comportamiento está documentado en los sockets de Windows (Nota: si se abre un socket, se realiza una llamada a setsockopt y luego se realiza una llamada a sendto, Windows Sockets realiza una llamada de función de enlace implícita). Pero yo No estoy seguro de que este sea el caso para otras implementaciones. Además, mi opinión sobre las llamadas implícitas es que es un mal hábito. – claf

0

Me falta algo, ¿por qué no usa el socket udp para enviar datos? Comience con sendto y luego use la función recvfrom para leer los datos entrantes; también obtiene como bonificación la dirección desde la cual se enviaron los datos, allí mismo para que envíe una respuesta.

+0

Algunos protocolos requieren que le importe qué número de puerto está usando en su extremo. Por ejemplo, los clientes [TFTP] (http://tools.ietf.org/html/rfc1350) lo usan para diferenciar entre múltiples transferencias simultáneas del mismo servidor. El servidor no puede enviar de vuelta desde el mismo puerto, cada transferencia de archivos requiere que el servidor envíe desde un puerto de origen diferente. Sin embargo, el servidor responde a la dirección de origen y al puerto de los clientes tal como lo describió. – doug65536

+1

En mi ejemplo específico, al usar un nuevo socket para cada transferencia, al hacer ciegamente 'sendto' se seleccionará implícitamente un puerto de origen, pero puede haber otros protocolos en los que no importa cuál sea el número de puerto antes de hacerlo' sendto' . – doug65536

+0

@ doug65536 es un ejemplo válido, pero la pregunta original no contenía ningún detalle específico de por qué. – Jonke

168

Otra opción es especificar el puerto 0 a bind(). Esto le permitirá vincularse a una dirección IP específica (en caso de que tenga múltiple instalado) mientras aún enlaza a un puerto aleatorio. Si necesita saber qué puerto fue elegido, puede usar getsockname() después de que se haya realizado la vinculación.

+18

La vinculación al puerto 0 es la forma oficial documentada de vincularse a un puerto aleatorio asignado al sistema operativo. –

+0

Documentado dónde? No es que esté diciendo que esto está mal, quiero ver una declaración autorizada. –

+8

Está en la documentación ['bind()'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550.aspx): "si el puerto se especifica como cero, el servicio El proveedor asigna un puerto único a la aplicación desde el rango del puerto cliente dinámico. En Windows Vista y versiones posteriores, el rango del puerto cliente dinámico es un valor entre 49152 y 65535. Este es un cambio de Windows Server 2003 y anterior era un valor entre 1025 y 5000 ... La aplicación puede usar getsockname después de llamar a bind para conocer la dirección y el puerto que se ha asignado al socket. " –

Cuestiones relacionadas