socket bind always returns 0, why?

Discussion in 'C++' started by oxkfame@gmail.com, May 27, 2014.

  1. Guest

    The following code returns 0 from the bind, even when netstat clearly shows that the port is taken by another process, ie the following function will always return true. Why?

    bool isPortAvailable( int port )
    {
    SOCKET candidateSocket;

    if(( candidateSocket = socket( AF_INET, SOCK_STREAM, 0 )) == -1 )
    return false;

    struct sockaddr_in serverAddress;
    memset (&serverAddress, 0, sizeof (serverAddress));

    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = htonl( INADDR_ANY );
    serverAddress.sin_port = htons( port );

    if( ::bind( candidateSocket, (struct sockaddr*)&serverAddress, sizeof( serverAddress )) != 0 )
    {
    closesocket( candidateSocket );
    return false;
    }

    closesocket( candidateSocket );
    return true;
    }
     
    , May 27, 2014
    #1
    1. Advertisements

  2. shows that the port is taken by another process, ie the following
    function will always return true. Why?
    Poor implementation, probably. 'bind' is not a Standard C++ function.
    You're much better off asking about it in a newsgroup dedicated to your
    OS or platform.

    V
     
    Victor Bazarov, May 27, 2014
    #2
    1. Advertisements

  3. Guest

    , May 27, 2014
    #3
  4. Guest

    Why close it?

    Brian
    Ebenezer Enterprises
    http://webEbenezer.net
     
    , May 27, 2014
    #4
  5. Geoff Guest

    My first guess would be that the other process has the port on a
    distinct IP address, your bind is to INADDR_ANY. This would let your
    process have a port listening on 0.0.0.0:port which, IIRC, is distinct
    from another process listening on 127.0.0.1:port for example. To prove
    this guess correct, use the same IP address to which the other process
    is bound and see if this function fails.
     
    Geoff, May 28, 2014
    #5
  6. Guest

    Thanks, I've changed it to LOOPBACK, but it didn't change anything. I still see two bindings in netstat:
    [./]$ sudo netstat -lptu |grep 1908
    tcp 0 0 localhost:19080 *:* LISTEN 12273/Test
    tcp 0 0 localhost:19080 *:* LISTEN 12273/Test
     
    , May 28, 2014
    #6
  7. Geoff Guest

    I think you may have misunderstood my intent. You need to identify the
    IP address AND the port in use by the other process in order to test
    that your function will return failure if the port is unavailable.

    My use of the loopback address was merely to give an example. A TCP/IP
    port is uniquely identified by two criteria: The IP address AND the
    port. One can have two or more processes listening on the same port if
    their IP addresses are different, this is called multihoming and
    routing of this type is OT in this group.

    If I were you I would give two arguments to your test function: the IP
    address you wish to associate with the port, and the port. If bind()
    returns no error in that case, the port is available and it should
    fail if another process has that combination of port and IP.
     
    Geoff, May 28, 2014
    #7
  8. Guest

    I have this code

    #include <tcp_server.hh>
    #if !defined(CMW_WINDOWS)
    #include <netinet/in.h>
    #include <sys/socket.h>
    int const SOCKET_ERROR=-1;
    #endif

    #include <ErrorWords.hh>
    #include <close_socket.hh>
    #include <getaddrinfo_wrapper.hh>

    sock_type cmw::tcp_server (uint16_t port)
    {
    auto res = makeResPtr(nullptr, port, SOCK_STREAM, AI_PASSIVE);
    for (auto rp = res.get(); rp != nullptr; rp = rp->ai_next) {
    sock_type sock = ::socket(rp->ai_family, rp->ai_socktype, 0);
    if (-1 == sock) continue;

    int on = 1;
    if :):setsockopt(sock, SOL_SOCKET, SO_REUSEADDR
    , (char const*)&on, sizeof(on)) < 0)
    throw failure("tcp_server setsockopt: ") << GetError();

    if (-1 == ::bind(sock, rp->ai_addr, rp->ai_addrlen)) {
    failure fail("tcp_server bind ");
    fail << GetError();
    close_socket(sock);
    throw fail;
    }

    if :):listen(sock, SOMAXCONN) == SOCKET_ERROR)
    throw failure("tcp_server listen ") << GetError();

    return sock;
    }
    throw failure("tcp_server failed");
    }


    I've tested it more on Linux than on Windows. Maybe
    it has a problem on Windows. I'm not sure about the
    SOCKET_ERROR stuff or if I should just use -1 on Windows.

    Brian
    Ebenezer Enterprises
    http://webEbenezer.net
     
    , May 29, 2014
    #8
  9. Guest

    Now I have this:

    #include <tcp_server.hh>
    #if !defined(CMW_WINDOWS)
    //#include <netinet/in.h>
    int const SOCKET_ERROR=-1;
    #endif

    #include <ErrorWords.hh>
    #include <getaddrinfo_wrapper.hh>
    #include <socket_wrapper.hh>

    sock_type cmw::tcp_server (uint16_t port)
    {
    auto res = makeResPtr(nullptr, port, SOCK_STREAM, AI_PASSIVE);
    for (auto rp = res.get(); rp != nullptr; rp = rp->ai_next) {
    socket_wrapper sock(rp->ai_family, rp->ai_socktype);
    if (-1 == sock.value()) continue;

    int on = 1;
    if :):setsockopt(sock.value(), SOL_SOCKET, SO_REUSEADDR
    , (char const*)&on, sizeof(on)) < 0)
    throw failure("tcp_server setsockopt: ") << GetError();

    if :):bind(sock.value(), rp->ai_addr, rp->ai_addrlen) != 0)
    throw failure("tcp_server bind ") << GetError();

    if :):listen(sock.value(), SOMAXCONN) == SOCKET_ERROR)
    throw failure("tcp_server listen ") << GetError();

    return sock.release();
    }
    throw failure("tcp_server failed");
    }

    namespace cmw {

    class socket_wrapper {
    bool released;
    sock_type sock;

    public:
    socket_wrapper (int, int);
    ~socket_wrapper ();
    sock_type value () { return sock; }
    sock_type release ()
    {
    released = true;
    return sock;
    }
    };
    }

    #include <socket_wrapper.hh>
    #include <close_socket.hh>

    #if !defined(CMW_WINDOWS)
    #include <sys/socket.h>
    #endif

    cmw::socket_wrapper::socket_wrapper (int family, int type) : released(false)
    ,sock:):socket(family, type, 0))
    {}

    cmw::socket_wrapper::~socket_wrapper ()
    {
    if (!released) close_socket(sock);
    }

    Comments welcome.

    Brian
    Ebenezer Enterprises
    http://webEbenezer.net
     
    , May 31, 2014
    #9
  10. Why do we need ::?
     
    Seungbeom Kim, Jun 2, 2014
    #10
  11. Guest

    To avoid ambiguity. There's nothing preventing someone
    from having a function called "socket" in a namespace
    and then:

    using abc::socket;

    I believe ::socket indicates we're talking about socket
    symbol in global namespace.
     
    , Jun 2, 2014
    #11
  12. Öö Tiib Guest

    Usage of 'bind' instead of '::bind' can already bring rather fun compiling
    problems because of 'std::bind'. Some style guides even require prefixing
    every name that is not namespace name and is in global namespace
    with '::'.
     
    Öö Tiib, Jun 3, 2014
    #12
  13. Jorgen Grahn Guest

    Nothing prevents that, except that that someone is either
    (a) doing it in a header file, which is very bad practice
    (b) doing it in the same source file, in which case he'll immediately
    see your real socket() call fail and has to fix it.

    /Jorgen
     
    Jorgen Grahn, Jun 3, 2014
    #13
  14. Guest


    For shared code it makes sense to me to use the :: prefix.
    If your code is used with another library that has the
    poor practice, then your user won't have to debug your
    code for you.

    Brian
    Ebenezer Enterprises
    http://webEbenezer.net
     
    , Jun 3, 2014
    #14
  15. True, but as long as there's no such ambiguity, I don't think it is
    wrong not to use the prefix, whereas your comment of "correcting" the
    missing prefix seemed to indicate that you considered it as something
    more serious than just a style issue.

    In addition, do you believe we should put the prefix for every name in
    the global namespace, e.g. ::waitpid, ::size_t, ::sockaddr_in, ::tzname,
    ::eek:ptarg, ::pthread_create, etc.? If not, what's your criterion?
     
    Seungbeom Kim, Jun 3, 2014
    #15
  16. Guest

    If it's a compile-time issue, I agree it's simple to fix.
    I think it's potentially more than a compile-time problem
    though.
     
    , Jun 3, 2014
    #16
  17. Guest

    I just changed some sockaddr_in6 symbols to ::sockaddr_in6.
    Thanks.
     
    , Jun 3, 2014
    #17
  18. I think that, with the same logic or a similar one, one could advocate
    prefixing "this->" (or even "classname::") to all uses of member names:
    e.g. ::bind or std::bind or this->bind.
    Are there any style guides that recommend or require this?
     
    Seungbeom Kim, Jun 4, 2014
    #18
  19. I also use it, not mainly for disambiguation but for readability.
    Unqualified functions/types are almost always members of the current class
    or namespace.
    It's a convention like appending _ or prepending m_ to member variables.

    Tobi
     
    Tobias Müller, Jun 5, 2014
    #19
  20. Öö Tiib Guest

    None that I know of. Reason is likely that 'this->' is 6 characters to type
    ('classname::' may be even more). On the contrary ... several style guides
    suggest against writing redundant 'this->' (or 'classname::'). Some
    seem to aim making that always redundant too. For example if to require
    special prefixes or suffixes to member names and to forbid hiding
    non-private names from base classes then there's never need to write
    'this->' or 'classname::'.
     
    Öö Tiib, Jun 5, 2014
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.