newbie: socket api

Discussion in 'C++' started by Thomas Kaufmann, Dec 26, 2012.

  1. 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
    Thomas Kaufmann, Dec 26, 2012
    #1
    1. Advertising

  2. On 12/26/2012 4:56 PM, Thomas Kaufmann wrote:
    > 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 do not respond to top-posted replies, please don't ask
    Victor Bazarov, Dec 26, 2012
    #2
    1. Advertising

  3. Thomas Kaufmann

    Ian Collins Guest

    Thomas Kaufmann wrote:
    > 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?

    --
    Ian Collins
    Ian Collins, Dec 26, 2012
    #3
  4. Am Mittwoch, 26. Dezember 2012 23:02:08 UTC+1 schrieb Ian Collins:
    > Thomas Kaufmann wrote:
    >
    > > 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?
    >
    >
    >
    > --
    >
    > Ian Collins


    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>
    Thomas Kaufmann, Dec 26, 2012
    #4
  5. Thomas Kaufmann

    Ian Collins Guest

    Thomas Kaufmann wrote:
    >


    ** 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;
    };

    --
    Ian Collins
    Ian Collins, Dec 26, 2012
    #5
  6. In article <>,
    Thomas Kaufmann <> wrote:
    >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.
    Miquel van Smoorenburg, Dec 26, 2012
    #6
  7. Thomas Kaufmann

    Guest

    On Wednesday, December 26, 2012 3:56:26 PM UTC-6, Thomas Kaufmann wrote:
    > 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
    , Dec 27, 2012
    #7
  8. 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
    Thomas Kaufmann, Dec 27, 2012
    #8
  9. Thomas Kaufmann

    Jorgen Grahn Guest

    On Wed, 2012-12-26, Miquel van Smoorenburg wrote:
    > In article <>,
    > Thomas Kaufmann <> wrote:
    >>Here is my code:
    >>
    >>void* InitAndConnect(int sockfd, int family, char *ip) {

    ....

    > 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

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Dec 29, 2012
    #9
  10. Ian Collins wrote:
    > 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.

    >> 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;
    > };
    Bill Cunningham, Dec 31, 2012
    #10
  11. Thomas Kaufmann

    Guest

    On Wednesday, December 26, 2012 11:58:08 PM UTC+1, Miquel van Smoorenburg wrote:
    > 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.
    , Dec 31, 2012
    #11
  12. Thomas Kaufmann

    Jorgen Grahn Guest

    On Mon, 2012-12-31, Bill Cunningham wrote:
    > Ian Collins wrote:
    >> 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.


    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().

    >>> bzero(&servaddr, sizeof(servaddr) );
    >>> servaddr.sin6_family = AF_INET;

    ....

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Jan 1, 2013
    #12
  13. Jorgen Grahn wrote:
    > 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().
    >
    >>>> bzero(&servaddr, sizeof(servaddr) );
    >>>> servaddr.sin6_family = AF_INET;


    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
    Bill Cunningham, Jan 4, 2013
    #13
  14. Thomas Kaufmann

    Jorgen Grahn Guest

    On Fri, 2013-01-04, Bill Cunningham wrote:
    > Jorgen Grahn wrote:
    >> 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().
    >>
    >>>>> bzero(&servaddr, sizeof(servaddr) );
    >>>>> servaddr.sin6_family = AF_INET;

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

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Jan 5, 2013
    #14
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Timothy Grant
    Replies:
    5
    Views:
    405
    Timothy Grant
    Aug 6, 2008
  2. Laszlo Nagy
    Replies:
    1
    Views:
    4,761
    Mark Wooding
    Jan 27, 2009
  3. Jean-Paul Calderone
    Replies:
    0
    Views:
    945
    Jean-Paul Calderone
    Jan 27, 2009
  4. Laszlo Nagy
    Replies:
    0
    Views:
    526
    Laszlo Nagy
    Feb 1, 2009
  5. Steve Holden
    Replies:
    0
    Views:
    645
    Steve Holden
    Feb 1, 2009
Loading...

Share This Page