socket bind always returns 0, why?


O

oxkfame

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

Advertisements

V

Victor Bazarov

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?

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
 
W

woodbrian77

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 )
::socket

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

Why close it?
return true;
}


Brian
Ebenezer Enterprises
http://webEbenezer.net
 
G

Geoff

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

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

oxkfame

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
 
Ad

Advertisements

G

Geoff

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

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

woodbrian77

You will probably need to add the following before bind:

int one=1;
setsockopt(candidateSocket , SOL_SOCKET, SO_REUSEADDR, (const char*)
&one, sizeof(one));

Despite the name SO_REUSEADDR is documented to avoid binding to the same
port if there is already "an active listening socket bound to the
address".

Note that this line has an opposite effect on Windows, they were probably
also confused by the name.

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
 
W

woodbrian77

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
 
W

woodbrian77

Why do we need ::?

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

Advertisements

Ö

Öö Tiib

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.

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 '::'.
 
J

Jorgen Grahn

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

using abc::socket;

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
 
W

woodbrian77

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.


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
 
S

Seungbeom Kim

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.

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

woodbrian77

You do realize this is a compile-time issue, right? One that is
dead simple to fix if one runs across it? No debugging required.

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

Advertisements

W

woodbrian77

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?

I just changed some sockaddr_in6 symbols to ::sockaddr_in6.
Thanks.
 
S

Seungbeom Kim

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 '::'.

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

Tobias Müller

Seungbeom Kim said:
Why do we need ::?

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
 
Ad

Advertisements

Ö

Öö Tiib

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?

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::'.
 

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

Top