Используйте bind
для привязки вашего сокета к порту 0, что позволит вам использовать getsockname
для получения порта. Вы также можете привязать свой сокет к определенному порту, если хотите.
например (при условии сокета IPv4, без проверки ошибок):
struct sockaddr_in sin = {};
socklen_t slen;
int sock;
short unsigned int port;
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = 0;
bind(sock, (struct sockaddr *)&sin, sizeof(sin));
/* Now bound, get the address */
slen = sizeof(sin);
getsockname(sock, (struct sockaddr *)&sin, &slen);
port = ntohs(sin.sin_port);
В качестве альтернативы, если вы общаетесь с одним сервером, вы можете использовать connect
на своем сокете UDP (что также дает вам удобный побочный эффект: вы можете использовать send
вместо sendto
и сделать Сокет UDP принимает дейтаграммы только от вашего «подключенного» партнера), затем используйте getsockname
для получения вашего локального порта / адреса. Вы все еще можете связать свой сокет до использования connect
.
например:
struct sockaddr_in sin = {};
socklen_t slen;
int sock;
short unsigned int port;
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
/* set sin to your target host... */
...
connect(sock, (struct sockaddr *)&sin, sizeof(sin));
/* now retrieve the address as before */
slen = sizeof(sin);
getsockname(sock, (struct sockaddr *)&sin, &slen);
port = ntohs(sin.sin_port);