I need to get the IP address of a connection to see if it has already connected previously (checking against a list of ips, if it has connected previously but isnt connected anymore, it will say offline). (using nonblocking sockets)
How can I get the IP without first accepting it.
///
case FD_ACCEPT:
int W;
for(W = 0;W <= ListView_GetItemCount(GetDlgItem(HwND,IDC_IPLIST));W++){
So then im just gonna check the IP against the list view to see if it had connected before. If it has, I want to use the same socket number it was using last time.
This is how I'm accepting connections right now
case FD_ACCEPT:
while(Client[F] != NULL)
{
F++;
}
Client[F]=accept(wParam,(LPSOCKADDR)&ServAdr,&AdrLen);
break;
so to break it down...
I want to check incoming connections against an IP list of previous connections. This list will have the IP and whether its online/offline (connected/not connected). If it has connected before I want it to show Online when I accept the new connection, and use the same socket number it used last time instead of using a new one all together. If it hasn't I want it to be added to the list. (the list will have the socket number)
If this doesnt make much sense I'll try and clarify a bit more.
What you are asking for cannot be done with accept(). You do not have access to a connection's information until after it has been accepted and a new SOCKET handle allocated. To get the connection info pre-acceptance, you have to use the callback functionality of WSAAccept() instead.
Either way, there is no way to reuse an existing SOCKET handle for a new connection. Each accepted connection must have its own unique SOCKET handle. You can certainly associate the new connection from a previously-seen IP with an existing slot in your ListView, though.
If by socket number you mean the number returned by accept(), you can't rely on it's value at all. I mean, if the remote host disconnects and connects again the value returned by accept() will most probably be different. It does not make sense to rely on this number.
If by socket number you mean the position in your array, you can assign the value returned by accept() to temporary variable:
SOCKET tmpSock;
sockaddr_in tmpAddr;
int namelen;
typedef struct { /*...*/ } TClient;
TClient Client[MAX_CLIENTS];
/*...*/
tmpSock = accept(/*...*/);
namelen = sizeof(tmpAddr);
getpeername(tmpSock, (sockaddr*)&tmpAddr,&namelen);
/*...*/
//looking for tmpAddr.sin_addr in your list and calculating
//the list position - F
/*...*/
Client[F].Socket = tmpSock;
Client[F].IsConnected = true;
Client[F].Address = tmpAddr.sin_addr;
Have in mind that after the listen() call the OS kernel will accept all incoming connection to the port/local IP set by you. It means that the connect() of remote host will return successfully whether you call accept() or not (provided you have space in listen queue). Calling accept() will only allow you to interact with the socket. It will not change the connection state seen by the remote host.
I'm not sure the is possible nor an efficient specification to achieve what you want. I would either:
Accept any connection and then check the IP address, disconnecting connections which are not in the list
(This probably isn't suitable for you) Configure an upstream firewall, such that only allowed IP addresses are allowed through.
If you bind to a wildcard address (INADDR_ANY), then the IP address used for communication isn't determined until a connection comes in (it will be one from the interface the packets are passing through). The same listening socket can result in accepted connections on more than one IP address.
If you bind to a specific address, then you already know the address you bound to.
Related
I have a system that can start multiple instances.
Every instance has a client and a server.
They are connected over socket/TCP
Every instance is started by starting a client.
The client starts (checks if IP is available, if not increase the IP by 1, checks again ...) -
The client starts the server with the free IP and connects to it. (for legacy reasons has to be like this)
Instance numbers 2, 3, 4, 5 work without issues.
...
Instance number 6. -> Fails on checking if the first IP in the range is available.
To check if IP is already in use, I do not close the socket on the server side so that it can accept the additional connection.
On the client-side, I check if I can connect to the server-side with the following code:
bool CheckIPInUse(char *ip)
{
bool ret = false;
int port = 12345;
int sock;
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
// **non blocking** because I want the check to be fast.
sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
inet_pton(AF_INET, ip, &serv_addr.sin_addr);
int ret_conn = connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (ret_conn == 0){
fprintf(stdout, "connected");
ret = true;
}
else if (ret_conn < 0 && (errno != EINPROGRESS)){
fprintf(stdout, "failed to connect");
}
else
{
int check_if_connected = 10;
while (check_if_connected--)
{
socklen_t len = sizeof(serv_addr);
int ret_getpeer = getpeername(sock, (struct sockaddr *)&serv_addr, &len);
if (ret_getpeer == 0)
{
fprintf(stdout, "connected");
ret = true;
break;
}
usleep(100000);
}
}
close(sock);
return ret;
}
This works for the first 5 instances.
6th instance fails to connect to the first IP in range and tries to start the server with IP which is already in use. (always the 6th).
Is there any better way to check programmatically if IP/Port is already busy?
Any ideas on what to check. for failure in the instance number 6?
The only way to check if an ip/port on a server is available is to bind() to it. If it worked, it was available (but not any more).
Any approach that involves a test connect()ion first, to see if it fails, or anything along the lines of poking somewhere in /proc to see which IPs and ports are in use -- nothing along these lines will ever be 100% foolproof. That's because even if you reach the conclusion that the port is available, it may no longer be by the time you get around to try to bind() to it.
Now, you can take, as a starting position, that a particular IP and/or port range is reserved for your application's use, and you only wish to arbitrate IP/port allocation between different instances of your application. In that case you can do that pretty much whatever you want, you're not limited to attempting to actually start instances of your application, and hope for the best. One simplistic approach is to use lock files in /var/tmp to represent all possible IP/port combination, and have your application try, in turn, to acquire a lock on the corresponding lock file, first, and once it's official, and the lock file is acquired, then the corresponding IP/port then can be established at your leisure, but the lock file must remain locked until the IP/port is no longer in use.
But in terms of attempting to check if a socket port is available, or not, the only way to do it is to bind() it, because that, by definition, is what it does. You could attempt to implement a multi-layered approach, like trying to connect() first, and then attempt to bind() it, and if the bind() fails, then keep looking for a free port. But that's creating extra complexity, without much of a benefit.
Did you check that the server did not meet its maximum backlog length ?
You may be getting "connection refused" if the server you are trying to connect to
has more pending connections then the defined backlog.
So if multiple clients are testing at the same time, one of them may encounter this.
The most probable cause of your problem is that your client is getting a connect from the server due to the listen queue. The best way to avoid this problem is to close the socket on which you call accept(2) once all the instances are in use, and reopen it again when any of the server instances are finished.
The listen queue makes the kernel to accept (send the SYN/ACK segment) connections on the otherwise not yet open socket waiting, and this will make the connection establishment quicker for the next server instances if many such connections are entering in the system. All those connections are handled in the accept(2) socket, so the best way to accept five such connections is to close the accept socket as soon as the last connection has been established (this will not avoid the problem if a connection happens to enter the server in the time between one accept(2) and the next, but the connection so established will be closed as soon as the accept socket is still open)
In my opinion, you should have a master server process that forks new processes to handle the different connection and closes the accept socket as soon as it reaches the full capacity. Once one of the servers attending the connections closes one of them, it should reopen the accept socket and accept a new connection.
IMHO, also the most robust way of implementing such a system is to allow the extra connections to get in, but not attend them, so the connection remains open in case a new client happens to enter, and it can close it if the server doesn't attend it in a timeout interval. Having a sixth client already connected, but waiting for the server to say hello, will leave you in a state in which you can start talking to the server as soon as the last service ends.
I use the router-dealer pattern from 0MQ. Now I want to store the client's address. I know that the first message from the client is the address, IP + portno I guess. Or rather recv() from the router socket puts the address in front of a received packet. But how do I handle this address, e.g. printing out or storing it for further outgoing messages? What type is it?
Here's the Guide explanation on this: http://zguide.zeromq.org/page:all#The-Request-Reply-Mechanisms
The ROUTER manages a set of connections, and keeps an 'identity' for each connection, which is a random number, like a handle. It tells you this identity on each message, as a first frame. It's a binary value, so you can't print it as-is.
The DEALER can override the ROUTER's internal identity by telling it, "use this ID" at connection time. That's what the zmq_setsockopt ZMQ_IDENTITY option does. We use this when nodes have some unique, often string, ID that has some meaning to the application.
the first part of the message is the identity of the sender (dealer) what you can set on the dealer side, with the zmq_setsockopt function (before connecting to the router). it's a maximum 255 char long string. if you don't set it, there will be some random unique thing, starting with #0 char.
so it's not the ip+port of your dealer by default, but you can put there that info if you like.
I am working on implementing UpNP on C++, and I need to get the local internal IP address assigned by the router to make the sockets works. The address I need is the one that appears on routers where it shows the computers connected to the router and the local IP assigned to each computer. I am using this:
PHOSTENT Addr = NULL;
char Host[MAX_PATH];
if( gethostname(Host, sizeof(Host)) == 0 )
{
Address = gethostbyname( Host );
if( Address != NULL )
{
//*(struct in_addr *)Address->h_addr_list[0]) <- this is my address
}
}
This works fine on the computer I am testing, but that computer has only one network card, so I was wondering if maybe when a computer has more than one card or network device, Address->h_addr_list[0] may not be the one I need and it could be in another index of that array.
Will [0] always retrieve the IP assigned by the router?
(Assuming winsock here, as per previous question)
You shouldn't assume that the first address is the correct one (as there may be multiple interfaces, and more than one may be active)
I'd recommend enumerating addresses using either getaddrinfo with an empty pNodeName argument, or GetAdaptersAddresses.
Both of these return a linked lists with your system's registered addresses
... get the local internal IP address assigned by the router ...
Note that in some cases, the machine's IP address will be manually assigned, but the user will still want to use UPnP.
On Linux, it is suggested to use getaddrinfo(3) instead of gethostbyname(3), perhaps Winsocks has made a similar transition?
On Linux, it is common for /etc/hosts to have loopback entries also accessible by hostname; /etc/gai.conf can be used to configure the sort order of returned addresses, and possibly a loopback address will be returned. Does Winsock make it that easy for sysadmins to change the order of returned addresses?
Don't forget that a system may legitimately have multiple upstream routers: a laptop with an EV-DO or EDGE or similar cellular data connection and a wireless or wired Ethernet will have multiple IPs, multiple upstream routers, and the routing table will be consulted to figure out which one should be used to send each packet.
Can you use either (a) the address used by clients to contact you? (getsockname(2) will return the local address used on a specific socket.) (b) ask the user to select among the list of IP addresses, if there are several? Binding to N of M interfaces would be nice, so users can select which networks get the services and which networks are left alone.
I have in my application a failure that arose which does not seem to be reproducible. I have a TCP socket connection which failed and the application tried to reconnect it. In the second call to connect() attempting to reconnect, I got an error result with errno == EADDRNOTAVAIL which the man page for connect() says means: "The specified address is not available from the local machine."
Looking at the call to connect(), the second argument appears to be the address to which the error is referring to, but as I understand it, this argument is the TCP socket address of the remote host, so I am confused about the man page referring to the local machine. Is it that this address to the remote TCP socket host is not available from my local machine? If so, why would this be? It had to have succeeded calling connect() the first time before the connection failed and it attempted to reconnect and got this error. The arguments to connect() were the same both times.
Would this error be a transient one which, if I had tried calling connect again might have gone away if I waited long enough? If not, how should I try to recover from this failure?
Check this link
http://www.toptip.ca/2010/02/linux-eaddrnotavail-address-not.html
EDIT: Yes I meant to add more but had to cut it there because of an emergency
Did you close the socket before attempting to reconnect? Closing will tell the system that the socketpair (ip/port) is now free.
Here are additional items too look at:
If the local port is already connected to the given remote IP and port (i.e., there's already an identical socketpair), you'll receive this error (see bug link below).
Binding a socket address which isn't the local one will produce this error. if the IP addresses of a machine are 127.0.0.1 and 1.2.3.4, and you're trying to bind to 1.2.3.5 you are going to get this error.
EADDRNOTAVAIL: The specified address is unavailable on the remote machine or the address field of the name structure is all zeroes.
Link with a bug similar to yours (answer is close to the bottom)
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294599
It seems that your socket is basically stuck in one of the TCP internal states and that adding a delay for reconnection might solve your problem as they seem to have done in that bug report.
This can also happen if an invalid port is given, like 0.
If you are unwilling to change the number of temporary ports available (as suggested by David), or you need more connections than the theoretical maximum, there are two other methods to reduce the number of ports in use. However, they are to various degrees violations of the TCP standard, so they should be used with care.
The first is to turn on SO_LINGER with a zero-second timeout, forcing the TCP stack to send a RST packet and flush the connection state. There is one subtlety, however: you should call shutdown on the socket file descriptor before you close, so that you have a chance to send a FIN packet before the RST packet. So the code will look something like:
shutdown(fd, SHUT_RDWR);
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_LINGER,
(char *) &linger, sizeof(linger));
close(fd);
The server should only see a premature connection reset if the FIN packet gets reordered with the RST packet.
See TCP option SO_LINGER (zero) - when it's required for more details. (Experimentally, it doesn't seem to matter where you set setsockopt.)
The second is to use SO_REUSEADDR and an explicit bind (even if you're the client), which will allow Linux to reuse temporary ports when you run, before they are done waiting. Note that you must use bind with INADDR_ANY and port 0, otherwise SO_REUSEADDR is not respected. Your code will look something like:
int opts = 1;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *) &opts, sizeof(int));
struct sockaddr_in listen_addr;
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0;
listen_addr.sin_addr.s_addr = INADDR_ANY;
// todo: test for error
bind(fd, (struct sockaddr *) &listen_addr, sizeof(listen_addr));
// todo: test for addr
// saddr is the struct sockaddr_in you're connecting to
connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
This option is less good because you'll still saturate the internal kernel data structures for TCP connections as per netstat -an | grep -e tcp -e udp | wc -l. However, you won't start reusing ports until this happens.
I got this issue. I got it resolve by enabling tcp timestamp.
Root cause:
After connection close, Connections will go in TIME_WAIT state for some
time.
During this state if any new connections comes with same IP and PORT,
if SO_REUSEADDR is not provided during socket creation then socket bind()
will fail with error EADDRINUSE.
But even though after providing SO_REUSEADDR also sockect connect() may
fail with error EADDRNOTAVAIL if tcp timestamp is not enable on both side.
Solution:
Please enable tcp timestamp on both side client and server.
echo 1 > /proc/sys/net/ipv4/tcp_timestamps
Reason to enable tcp_timestamp:
When we enable tcp_tw_reuse, sockets in TIME_WAIT state can be used before they expire, and the kernel will try to make sure that there is no collision regarding TCP sequence numbers. If we enable tcp_timestamps, it will make sure that those collisions cannot happen. However, we need TCP timestamps to be enabled on both ends. See the definition of tcp_twsk_unique for the gory details.
reference:
https://serverfault.com/questions/342741/what-are-the-ramifications-of-setting-tcp-tw-recycle-reuse-to-1
Another thing to check is that the interface is up. I got confused by this one recently while using network namespaces, since it seems creating a new network namespace produces an entirely independent loopback interface but doesn't bring it up (at least, with Debian wheezy's versions of things). This escaped me for a while since one doesn't typically think of loopback as ever being down.
I am writing an XMLRPC client in c++ that is intended to talk to a python XMLRPC server.
Unfortunately, at this time, the python XMLRPC server is only capable of fielding one request on a connection, then it shuts down, I discovered this thanks to mhawke's response to my previous query about a related subject
Because of this, I have to create a new socket connection to my python server every time I want to make an XMLRPC request. This means the creation and deletion of a lot of sockets. Everything works fine, until I approach ~4000 requests. At this point I get socket error 10048, Socket in use.
I've tried sleeping the thread to let winsock fix its file descriptors, a trick that worked when a python client of mine had an identical issue, to no avail.
I've tried the following
int err = setsockopt(s_,SOL_SOCKET,SO_REUSEADDR,(char*)TRUE,sizeof(BOOL));
with no success.
I'm using winsock 2.0, so WSADATA::iMaxSockets shouldn't come into play, and either way, I checked and its set to 0 (I assume that means infinity)
4000 requests doesn't seem like an outlandish number of requests to make during the run of an application. Is there some way to use SO_KEEPALIVE on the client side while the server continually closes and reopens?
Am I totally missing something?
The problem is being caused by sockets hanging around in the TIME_WAIT state which is entered once you close the client's socket. By default the socket will remain in this state for 4 minutes before it is available for reuse. Your client (possibly helped by other processes) is consuming them all within a 4 minute period. See this answer for a good explanation and a possible non-code solution.
Windows dynamically allocates port numbers in the range 1024-5000 (3977 ports) when you do not explicitly bind the socket address. This Python code demonstrates the problem:
import socket
sockets = []
while True:
s = socket.socket()
s.connect(('some_host', 80))
sockets.append(s.getsockname())
s.close()
print len(sockets)
sockets.sort()
print "Lowest port: ", sockets[0][1], " Highest port: ", sockets[-1][1]
# on Windows you should see something like this...
3960
Lowest port: 1025 Highest port: 5000
If you try to run this immeditaely again, it should fail very quickly since all dynamic ports are in the TIME_WAIT state.
There are a few ways around this:
Manage your own port assignments and
use bind() to explicitly bind your
client socket to a specific port
that you increment each time your
create a socket. You'll still have
to handle the case where a port is
already in use, but you will not be
limited to dynamic ports. e.g.
port = 5000
while True:
s = socket.socket()
s.bind(('your_host', port))
s.connect(('some_host', 80))
s.close()
port += 1
Fiddle with the SO_LINGER socket
option. I have found that this
sometimes works in Windows (although
not exactly sure why):
s.setsockopt(socket.SOL_SOCKET,
socket.SO_LINGER, 1)
I don't know if this will help in
your particular application,
however, it is possible to send
multiple XMLRPC requests over the
same connection using the
multicall method. Basically
this allows you to accumulate
several requests and then send them
all at once. You will not get any
responses until you actually send
the accumulated requests, so you can
essentially think of this as batch
processing - does this fit in with
your application design?
Update:
I tossed this into the code and it seems to be working now.
if(::connect(s_, (sockaddr *) &addr, sizeof(sockaddr)))
{
int err = WSAGetLastError();
if(err == 10048) //if socket in user error, force kill and reopen socket
{
closesocket(s_);
WSACleanup();
WSADATA info;
WSAStartup(MAKEWORD(2,0), &info);
s_ = socket(AF_INET,SOCK_STREAM,0);
setsockopt(s_,SOL_SOCKET,SO_REUSEADDR,(char*)&x,sizeof(BOOL));
}
}
Basically, if you encounter the 10048 error (socket in use), you can simply close the socket, call cleanup, and restart WSA, the reset the socket and its sockopt
(the last sockopt may not be necessary)
i must have been missing the WSACleanup/WSAStartup calls before, because closesocket() and socket() were definitely being called
this error only occurs once every 4000ish calls.
I am curious as to why this may be, even though this seems to fix it.
If anyone has any input on the subject i would be very curious to hear it
Do you close the sockets after using it?