4

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";

10
  • Change your variable name. The name sin conflicts with the sin (trigonometry) function in the math library. Commented Oct 12, 2015 at 15:48
  • Make variable sockaddr sin before if's and initialize it in the enc of each if with your local sin. Commented Oct 12, 2015 at 15:48
  • 1
    @ThomasMatthews no, it is not. Commented Oct 12, 2015 at 15:55
  • @Status well its is sockaddr_in or sockaddr_in6 which is difference ... please post a code since I dont really understand what you mean :) Commented Oct 12, 2015 at 15:55
  • 1
    If you use the getaddrinfo()-API in POSIX, you don't have to worry about this detail, because it will automatically allocate the right address. Commented Oct 12, 2015 at 15:57

2 Answers 2

2

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 
Sign up to request clarification or add additional context in comments.

Comments

1

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

1 Comment

Don't call it sockaddr_un. That's the name of the struct used for UNIX domain sockets.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.