newbie: socket api

T

Thomas Kaufmann

Hi there,

I use the socket-API. My Problem is:

I have a function (yes, a function not a method). And I want return either the struct sockaddr_in or sockaddr_in6. How can do this? I tried a void-pointer but there is an error-message.

Best regards.

Thomas
 
V

Victor Bazarov

I use the socket-API. My Problem is:

I have a function (yes, a function not a method). And I want return either the struct sockaddr_in or sockaddr_in6. How can do this? I tried a void-pointer but there is an error-message.

This is covered in the FAQ 5.8. Please read the FAQ before posting.
You can find FAQ here: http://www.parashift.com/c++-faq/

V
 
I

Ian Collins

Thomas said:
Hi there,

Please wrap your lines!
I use the socket-API. My Problem is:

I have a function (yes, a function not a method). And I want return
either the struct sockaddr_in or sockaddr_in6. How can do this? I
tried a void-pointer but there is an error-message.

What did you try? What error did you get?
 
T

Thomas Kaufmann

Am Mittwoch, 26. Dezember 2012 23:02:08 UTC+1 schrieb Ian Collins:
Please wrap your lines!








What did you try? What error did you get?

Here is my code:

#include "unp.h"
#include "init.h"

#include <exception>

void* InitAndConnect(int sockfd, int family, char *ip) {

// I want return this struct
struct sockaddr sa;

if (family == AF_INET) {

try {

struct sockaddr_in servaddr;;

bzero(&servaddr, sizeof(servaddr) );
servaddr.sin_family = family;
servaddr.sin_port = htons(SERV_PORT);

if (inet_pton(family, ip, &servaddr.sin_addr) <= 0) {
perror("inet_pton-error: ");
}

connect(sockfd, (SA*) &servaddr, sizeof(servaddr) );

// critical line
sa = servaddr;

} catch(std::exception& e) {
cout << e.what() << endl;
}

} else if (family == AF_INET6) {

struct sockaddr_in6 servaddr;

bzero(&servaddr, sizeof(servaddr) );
servaddr.sin6_family = AF_INET;
servaddr.sin6_port = htons(SERV_PORT);
inet_pton(family, ip, &servaddr.sin6_addr);

connect(sockfd, (SA*) &servaddr, sizeof(servaddr) );

// critical line
sa = servaddr;
}

// does' work
return sa;
}

int main(int argc, char *argv[]) {

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
void* ptr = InitAndConnect(int sockfd, AF_INET, argv[1]) {

return 0;
}

Here are the errors:

xxx54@richard:~/myC++/unp/derplan> g++ -o init -Wall -pedantic -O3 init_test.cpp
init_test.cpp: In function ‘void* InitAndConnect(int, int, char*)’:
init_test.cpp:28:12: error: no match for ‘operator=’ in ‘sa = servaddr’
/usr/include/bits/socket.h:179:3: note: candidate is: sockaddr& sockaddr::eek:perator=(const sockaddr&)
init_test.cpp:46:12: error: no match for ‘operator=’ in ‘sa = servaddr’
/usr/include/bits/socket.h:179:3: note: candidate is: sockaddr& sockaddr::eek:perator=(const sockaddr&)
init_test.cpp:50:10: error: cannot convert ‘sockaddr’ to ‘void*’ inreturn
init_test.cpp: In function ‘int main(int, char**)’:
init_test.cpp:56:31: error: expected primary-expression before ‘int’
init_test.cpp:56:61: error: expected ‘,’ or ‘;’ before ‘{’ token
init_test.cpp:55:7: warning: unused variable ‘sockfd’
init_test.cpp:56:9: warning: unused variable ‘ptr’
init_test.cpp:59:1: error: expected ‘}’ at end of input
init_test.cpp: In function ‘void* InitAndConnect(int, int, char*)’:
init_test.cpp:51:1: warning: control reaches end of non-void function
xxx54@richard:~/myC++/unp/derplan>
 
I

Ian Collins

** Please clean up the mess that dreadful google interface makes of your
quotes.
Here is my code:

#include "unp.h"
#include "init.h"

#include <exception>

void* InitAndConnect(int sockfd, int family, char *ip) {

// I want return this struct
struct sockaddr sa;

Then why don't you?
if (family == AF_INET) {

try {

Why have a try block here?
struct sockaddr_in servaddr;;

bzero(&servaddr, sizeof(servaddr) );

Just use
sockaddr_in servaddr = {0};

rather than calling bzero.
servaddr.sin_family = family;
servaddr.sin_port = htons(SERV_PORT);

if (inet_pton(family, ip, &servaddr.sin_addr) <= 0) {
perror("inet_pton-error: ");

Should you carry on if this fails?
}

connect(sockfd, (SA*) &servaddr, sizeof(servaddr) );

// critical line
sa = servaddr;

} catch(std::exception& e) {
cout << e.what() << endl;
}

} else if (family == AF_INET6) {

struct sockaddr_in6 servaddr;

bzero(&servaddr, sizeof(servaddr) );
servaddr.sin6_family = AF_INET;
servaddr.sin6_port = htons(SERV_PORT);
inet_pton(family, ip, &servaddr.sin6_addr);

connect(sockfd, (SA*) &servaddr, sizeof(servaddr) );

// critical line
sa = servaddr;
}

// does' work
return sa;

Are you surprised?

You could return something like

struct Address
{
int family;
union {
sockaddr_in v4;
sockaddr_in6 v6;
} servaddr;
};
 
M

Miquel van Smoorenburg

Here is my code:

void* InitAndConnect(int sockfd, int family, char *ip) {

// I want return this struct
struct sockaddr sa;

You should return a struct sockaddr_storage, since a plain struct
sockaddr isn't big enough for a struct sockaddr_in6. That,
or a pointer of type struct sockaddr, that points to a
_in or _in6.
if (family == AF_INET) {

try {

struct sockaddr_in servaddr;;

bzero(&servaddr, sizeof(servaddr) );
servaddr.sin_family = family;
servaddr.sin_port = htons(SERV_PORT);

Should probably be something like

struct sockaddr_in *serveraddr = (struct sockaddr_in *)&sa;
servaddr->sin_family = family;
servaddr->sin_port = htons(SERV_PORT);
... etc
// does' work
return sa;

But why not use getaddrinfo() to do all the dirty work for you.
Note that you don't even have to pass in "family" since
getaddrinfo() figures that out for you.

int InitAndConnectchar *ip)
{
struct addrinfo hints = { 0 };
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

struct addrinfo *res;
int r = getaddrinfo(ip, SERV_PORT, &hints, &res);
if (r != 0) {
fprintf(stderr, "%s/%s: %s\n", ip, SERV_PORT,
gai_strerror(r));
return NULL;
}

int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock < 0)
return -1;
int ok = connect(sock, res->ai_addr, res->ai_addrlen);
if (ok != 0) {
close(sock);
sock = -1;
}
freeaddrinfo(res);

return sock;
}

Mike.
 
W

woodbrian77

Hi there,



I use the socket-API. My Problem is:



I have a function (yes, a function not a method). And I want return either the struct sockaddr_in or sockaddr_in6. How can do this? I tried a void-pointer but there is an error-message.

Here's some code similar to what Mike posted:
http://webEbenezer.net/misc/getaddrinfo_wrapper.cc
http://webEbenezer.net/misc/connect_wrapper.cc

Those files and others are part of the archive here --
http://webEbenezer.net/build_integration.html
..

Brian
Ebenezer Enterprises
http://webEbenezer.net
 
T

Thomas Kaufmann

Am Mittwoch, 26. Dezember 2012 22:56:26 UTC+1 schrieb Thomas Kaufmann:
Hi there,



I use the socket-API. My Problem is:



I have a function (yes, a function not a method). And I want return either the struct sockaddr_in or sockaddr_in6. How can do this? I tried a void-pointer but there is an error-message.


Thanks folks for your help!

Best regards

Thomas
 
J

Jorgen Grahn

....

But why not use getaddrinfo() to do all the dirty work for you.
Note that you don't even have to pass in "family" since
getaddrinfo() figures that out for you.

+1. For some bizarre reason, people seem to be unaware of
getaddrinfo(), even though it has existed for 10+ years and is
documented in the classic works on socket programmming.

Use it. It saves work, avoids bugs and provides features you'll
probably neglect to provide if you do it manually.

/Jorgen
 
B

Bill Cunningham

Ian said:
Thomas Kaufmann wrote:

I would just like to say this one thing about this code. I've worked with
the same functions in C with the unix socket api. I *think* bzero is
depricated for memset now.
 
G

goran.pusic

int r = getaddrinfo(ip, SERV_PORT, &hints, &res);
if (r != 0) {
fprintf(stderr, "%s/%s: %s\n", ip, SERV_PORT,
gai_strerror(r));
return NULL;
}
int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock < 0)
return -1;
A nitpick. Memory leak here: freeaddrinfo isn't called.

A get/freeaddrinfo wrapper, or use of ON_BLOCK_EXIT of ScopeGuard fame ;-) are on order.

Goran.
 
J

Jorgen Grahn

I would just like to say this one thing about this code. I've worked with
the same functions in C with the unix socket api. I *think* bzero is
depricated for memset now.

It is, but more importantly memset is standard C and C++; bzero never
was. And even more importantly, as stated two times upthread, all of
this messing about with memory and casts can be replaced with the
safer, more elegant and more powerful getaddrinfo().
....

/Jorgen
 
B

Bill Cunningham

Jorgen said:
It is, but more importantly memset is standard C and C++; bzero never
was. And even more importantly, as stated two times upthread, all of
this messing about with memory and casts can be replaced with the
safer, more elegant and more powerful getaddrinfo().

Oh yes. getaddrinfo packs the structs for you. It's a little newer
addition to the API though. Some people may not know of it. I have an old
UNIX networking book that doesn't mention it. And a newer one that shows
how.

Bill
 
J

Jorgen Grahn

Oh yes. getaddrinfo packs the structs for you. It's a little newer
addition to the API though. Some people may not know of it.

Yes, that was my point, and the reason I have mentioned it in three or four
postings now even though it's offtopic here.
I have an old
UNIX networking book that doesn't mention it. And a newer one that shows
how.

Which one is this older one, by the way?

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top