JamesTheProg
JamesTheProg

Reputation: 101

Get random port for socket

I know the question has been asked already, but i seem to be some kind of "special" since my code doesn't work. Instruction is "bind with port 0 and use getsockname to get port". What am i doing wrong...

struct sockaddr_in sa;

sa.sin_port=htons(0);
sa.sin_addr.s_addr=htonl(INADDR_ANY);
sa.sin_family=AF_INET;

int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr *serverptr = (struct sockaddr*)&sa;
bind(sock, serverptr,sizeof(sa));
socklen_t s=sizeof(sa);
int g=getsockname(sock,serverptr,&s);

g always prints as 0.

EDIT: it was so much simpler, just sa.sin_port Dumb question.

Upvotes: 0

Views: 1162

Answers (2)

Zibri
Zibri

Reputation: 9827

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int
main (int argc, char** argv)
{
  int sock;
  struct sockaddr_in name;
  char *addr;

  if(argc<2) {
     addr="0.0.0.0";
  } else {
     addr=argv[1];
  }
  /* Create the socket. */
  sock = socket (PF_INET, SOCK_STREAM, 0);
  if (sock < 0)
    {
      perror ("socket");
      exit (EXIT_FAILURE);
    }

  /* Give the socket a name. */
  name.sin_family = AF_INET;
  name.sin_port = htons (0);
  name.sin_addr.s_addr = inet_addr(addr);
  if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
    {
      perror ("bind");
      exit (EXIT_FAILURE);
    }

  int len = sizeof(name);
  int sn = getsockname(sock, (struct sockaddr *)&name, &len);
  printf("Port is %d\n",ntohs(name.sin_port));
  return sock;
}

Compile: gcc getport.c -o getport

Usage: ./getport [address]

Ouput:
./getport
Port is 31725
./getport 127.0.0.1
Port is 32064
./getport 1.2.3.4
bind: Cannot assign requested address

Upvotes: 0

Yury Schkatula
Yury Schkatula

Reputation: 5369

Most of Berkley Socket API functions use very simple convention: result returned is the operation success indication. So, zero means OK, negative means error. To play safe, you have always to check it, and your code lacks this verification for the socket(), bind(), and getsockname() calls:

...
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
    // log the error, etc
    return;
}
int res = bind(sock, serverptr, sizeof(sa));
if (res < 0) {
    // log the error, etc
    close(sock);
    return;
}
socklen_t s = sizeof(sa);
res = getsockname(sock, serverptr, &s);
if (res < 0) {
    // log the error, etc
    close(sock);
    return;
}
...

Upvotes: 1

Related Questions