Denis
Denis

Reputation: 81

Declaring variable with same name but different type

I am trying to make something with supports IPV4 or IPV6. The code is similar for these two so I tried something like this. Since the only difference in code later on depends on this sin variable how can I compile just one of them. Lets suppose "ipv" variable in IF statement is true or false depends on user input

//FOR IPV4
//struct sockaddr_in sin;
//FOR IPV6
//struct sockaddr_in6 sin;
//IPV4


// IPV4 ---------------------------------------
if (ipv){
  struct sockaddr_in sin;   
  if ( (s = socket(AF_INET, SOCK_STREAM, 0 ) ) < 0) { 
    perror("Chyba pri vytvareni socketu");  
    return -1;
  }


  sin.sin_family = AF_INET;     
  sin.sin_port = htons(port_number);
  sin.sin_addr.s_addr  = INADDR_ANY;
}

// IPV6 ---------------------------------------
else{

  struct sockaddr_in6 sin;
  if ( (s = socket(AF_INET6, SOCK_STREAM, 0 ) ) < 0) { 
    perror("Chyba pri vytvareni socketu");  
    return -1;
  }

  sin.sin6_family = AF_INET6;     
  sin.sin6_port = htons(port_number);
  sin.sin6_addr = in6addr_any;
  sin.sin6_flowinfo = 0;
}   

if (bind(s, (struct sockaddr *)&sin, sizeof(sin) ) < 0 ) {
    printf("error on bind\n"); return -1;  
}

if (listen(s, 5)) { 
    printf ("error on listen\n"); 
return -1;
}

sinlen = sizeof(sin);
pid_t pid;

while (1) {


    /* accepting new connection request from client,
    socket id for the new connection is returned in t */
    if ( (t = accept(s, (struct sockaddr *) &sin, &sinlen) ) < 0 ) {
      printf("error on accept\n");  /* accept error */
      return -1;
    }
continues .... not important 

this code will give me:

server.cpp: In function ‘int main(int, char**)’:  
server.cpp:132:35: error: ‘sin’ was not declared in this scope
   if (bind(s, (struct sockaddr *)&sin, sizeof(sin) ) < 0 ) {
                               ^
server.cpp:145:19: error: ‘sin’ was not declared in this scope
   sinlen = sizeof(sin);
               ^
make: *** [all] Error 1

So question is how can I make this done without writing the same code twice with different "sin";

Upvotes: 4

Views: 1962

Answers (2)

AndreyS Scherbakov
AndreyS Scherbakov

Reputation: 2788

It's a typical case when you might use a union.

typedef union {
    struct sockaddr_in v4;
    struct sockaddr_in6 v6;
} sockaddr_union;

sockaddr_union sin;

Then, when you know you're working with IPV4, use sin.v4 in place of sin, and when you know you're working with IPV6, use sin.v6

Upvotes: 1

Denis
Denis

Reputation: 81

I did it like this by using sockaddr_storage and its working well

struct sockaddr_storage sin;
struct sockaddr_in *sin4;
struct sockaddr_in *sin6;
// IPV4 ---------------------------------------
if (ipv == true){
    sin4 = (struct sockaddr_in*)&sin;   
    if ( (s = socket(AF_INET, SOCK_STREAM, 0 ) ) < 0) { 
         perror("Chyba pri vytvareni socketu");  
         return -1;
    }


    sin4->sin_family = AF_INET;     
    sin4->sin_port = htons(port_number);
    sin4->sin_addr.s_addr  = INADDR_ANY;
}

// IPV6 ---------------------------------------
else{

    sin6 = (struct sockaddr_in6*)&sin;
    if ( (s = socket(AF_INET6, SOCK_STREAM, 0 ) ) < 0) { 
        perror("Chyba pri vytvareni socketu");  
        return -1;
    }

    sin6->sin6_family = AF_INET6;     
    sin6->sin6_port = htons(port_number);
    sin6->sin6_addr = in6addr_any;
    sin6->sin6_flowinfo = 0;
}   

if (bind(s, (struct sockaddr *)&sin, sizeof(sin) ) < 0 ) {
    printf("error on bind\n"); return -1;  
}

if (listen(s, 5)) { 
    printf ("error on listen\n"); 
    return -1;
}

sinlen = sizeof(sin);
pid_t pid;

while (1) {


     /* accepting new connection request from client,
     socket id for the new connection is returned in t */
     if ( (t = accept(s, (struct sockaddr *) &sin, &sinlen) ) < 0 ) {
         printf("error on accept\n");  /* accept error */
     return -1;
     }
     continues .... not important 

Upvotes: 2

Related Questions