Checking if UDP port is opened already in C - c

LANG: C
How can I check if the UDP socket is already opened so I can increment the used port and send on the next socket, I don't have any idea how much sockets the server will need.
I also can't use port 0 as I have to start at a specific port.
Only solutions I have right now is either implement my own queue to trace open ports or try to read /proc/net/udp
Is there a defined API? also if no, can you submit a sample code that will trace opened ports used by my program?

If the port is already in use bind will fail. If it fails you only need to increment the port you are trying to use. Then save it for when you want to use the next port. Bind returns -1 when fails. Btw, are you using linux?
You can stablish a max and a min port number and when the port you want to use reach the max, set port equal to min (this is the simplest method).
Other methods will need shared memory or semaphores and locks.

Related

Is the new connected socket returned by accept() always bound to the same port as the listening socket?

I tested this on my machine by creating new connections until failure. On my machine new connect()/accept() requests fail* at near 700 socket connections (SOCK_STREAM); at the client/server respectively, on the loopback IP address. However the socket file descriptor returned by accept(), so far, is always bound to the same port as the listening socket.
My question is - If this behaviour is true for all machines then why is accept() limiting connections by creating connected sockets bound only to the same port as the listening socket? Couldn't the number of connections the server can make be increased greatly if the new sockets were bound to random ports (like connect() does)?
Also, why is accept(sock_fd, NULL, NULL) failing with "EFAULT - The addr argument is not in a writable part of the user address space." after nearly 700 successful iterations of the same call?
Similarly, why does, connect() fail with "EFAULT - The socket structure address is outside the user's address space." after nearly 700 successful iterations of the same call?
* EFAULT - Bad Address (after both accept()/connect()).
When you are listening, all connections will have the same port in the accept end of the connection (that is what is used as an identifier initially in order to establish the connection).
The local port number for the connecting part if not defined with a bind() can be anything. For the localhost device, the numbers can probably be recycled very fast on some OS, since there is no real need for lingering state of the TCP.
When it comes to having MANY connections on the same time, the amount of connections possible is limited by resources in your operating system per process. For Unix/Linux, this limit can be adjusted, put it is not advised to make the amount of FDs higher than default if using select(), since the libc size of the FDSET usually matches the default number of filedescriptors available per process. One trick around this is to create the socket, fork out children and let the children call accept(). Then each children can have many connections (apache and squid use this kind of model), increasing the total amount of connections possible on the same server port.
why is accept() limiting connections by creating connected sockets bound only to the same port as the listening socket? Couldn't the number of connections the server can make be increased greatly if the new sockets were bound to random ports (like connect() does)?
It doesn't impose any limitations. A connected TCP socket's "address" should be viewed as four parameters: srcip, srcport, dstip, dstport. So there's absolutely no need to bind accept()'ed socket to a random port.
Also, why is accept(sock_fd, NULL, NULL) failing with "EFAULT - The addr argument is not in a writable part of the user address space." after nearly 700 successful iterations of the same call?
Well, it's about OS internals. The amount of resources for any user process may (and should be) limited. Read your OS developer manual or such.

UDP based chat in C

I'm supposed to make a communicator in C, based on dgrams. I don't know what arguments should I pass to bind() function. I skimmed through most UDP-chat questions & codes here on StackOverflow but I still can't find any specific information on the issue.
What type of address structure should I use?
What port can I use? Any number bigger than 1024 ?
What IP adress do I bind my socket with? (most of people put INADDR_ANY but isn't it for receiving only?)
Also, do I need multiple sockets? One for receiving & another for sending messages.
What type of address structure should I use?
If you are using IPv4, use a sockaddr_in. If you want to use IPv6 instead, use a sockaddr_in6.
What port can I use? Any number bigger than 1024 ?
Yes, assuming no other program is already using that port number for its own UDP socket. (If another program is using the port number you chose, it will cause bind() to fail with errno EADDRINUSE)
What IP adress do I bind my socket with? (most of people put
INADDR_ANY but isn't it for receiving only?)
INADDR_ANY is what you generally want to use. It tells the OS that you want to receive incoming UDP packets on any of the computers network interfaces. (If you only wanted to receive UDP packets from a particular network interface, OTOH, e.g. only on WiFi, you could specify that network interface's IP address instead)
Also, do I need multiple sockets? One for receiving & another for
sending messages.
You can have multiple sockets if you want, but it's not necessary to do it that way. You can instead use a single socket for both sending and receiving UDP packets. One common pattern is to use a single socket, set to non-blocking mode, and something like select() or poll() to multiplex the input and output needs of your program. An alternative pattern would be to use two threads (one for sending and one for receiving), blocking I/O, and either one or two sockets (depending on whether you prefer to have the two threads share a socket, or give each thread its own socket). I prefer the single-threaded/single-socket/select() solution myself, as I think it is the least error-prone approach.

With C sockets, what determines the appearance of a socket's port?

When I create a socket, and bind it to a port, it will tell me that the socket is listening on the assigned port. For example,
Create socket.
Bind to port 7006
However, when I connect to another location, the port number appears to change from the outside only. As in, everything works as it should, it just looks like the port is different, and I want to know why.
A server program that took a connection from this socket, bound to 7006, said the address was
localhost:42566
A SOCK_DGRAM socket I made and bound to port 7008 read this address from recvfrom
localhost:a3fs-fileserver
I figure the a3fs-fileserver is just interpreted that way because it happened to have the port typically associated with a3fs-fileserver and getnameinfo tries to get and english service name when possible.
But why does it look different outside my program than inside? Note: This behavior works the same way between machines as well, I just happened to be testing on one for convenience.

Using C sockets: Address already in use

So the basic premise of my program is that I'm supposed to create a tcp session, direct traffic through it, and detect any connection losses. If the connection does break, I need to close the sockets and reopen them (using the same ports) in such a way that it will seem like the connection (almost) never died. It should also be noted that the two programs will be treated as proxies (data gets sent to them, if the connection breaks it gets stored until connection is fixed, then data is sent off).
I've done some research and gone ahead and used setsockopt() with the SO_REUSEADDR option to set the socket options so that I can reuse the address.
Here's the basic algorithm I do to detect a connection break using signals:
After initial setup of sockets, begin sending data
After x seconds, set a flag to false, which will prevent all other data from being sent
Send a single piece of data to let the other program know the connection is still open, reset timer to x seconds
If I receive same piece of data from the program, set the flag to true to continue sending
If I don't receive the data after x seconds, close the socket and attempt to reconnect
(step 5 is where I'm getting the error).
Essentially one program is a client(on one VM) and one program is a server(on another VM), each sending and receiving data to/from each other and to/from another program on each VM.
My question is: Given that I'm still getting this error after setting the socket options, why am I not allowed to re-bind the address when a connection has been detected?
The server is the one complaining when a disconnect is detected (I close the socket, open a new one, set the option, and attempt to bind the port with the same information).
One other thing of note is the way I'm receiving the data from the sockets. If I have a socket open, I'm basically reading it by doing the following:
while((x = recv(socket, buff, 1, 0)>=0){
//add to buffer
// send out to other program if connection is alive
}
Since I'm using the timer to close/reopen the socket, and this is in a different thread, will this prevent the socket from closing?
SO_REUSEADDR only allows limited reuse of ports. Specifically, it does not allow reuse of a port that some other socket is currently actively listening for incoming connections on.
There seems to be an epidemic here of people calling bind() and then setsockopt() and wondering why the setsockopt() doesn't fix an error that had already happened on bind().
You have to call setsockopt() first.
But I don't understand your problem. Why do you think you need to use the same ports? Why are you setting a flag preventing you from sending data? You don't need any of this. Just handle the errors on send() when and if they arise, creating a new connection when necessary. Don't try to out-think TCP. Many have tried, few if any have succeeded.

Get random port for UDP socket

I need to create a program that will communicate with other programs on the same computer via UDP sockets. It will read commands from stdin, and some of this commands will make it to send/receive packets without halting execution. I've read some information out there, but since I'm not familiar with socket programming and need to get this done quickly, I have the following questions:
I need to get a random unused port for the program to listen to, and reserve it so other programs can communicate with this and also the port isn't reserved by another program. I also need to store the port number on a variable for future usage.
Since the communication is across processes on the same machine, I'm wondering if I can use PF_LOCAL.
Also a code sample of the setup of such socket would be welcome, as well as an example of sending/receiving character strings.
Call bind() specifying port 0. That will allow the OS to pick an unused port. You can then use getsockname() to retreive the chosen port.
Answer by Remy Lebeau is good if you need a temporary port. It is not so good if you need a persistent reserved port because other software also uses the same method to get a port (including OS TCP stack that needs a new temporary port for each connection).
So the following might happen:
You call bind with 0 and getsockname() to get a port;
then save it into config (or into several configs) for future uses;
software that needs this port starts and binds the port.
Then you need to e.g. restart the software:
software stops and unbinds the port: the port can now be returned by bind(0) and getsockname() again;
e.g. TCP stack needs a port and binds your port;
software can't start because port is already bound.
So for "future uses" you need a port that is not in ephemeral port range (that's the range from which bind(host, 0) returns a port).
My solution for this issue is the port-for command-line utility.
If it being a random port is actually important, you should do something like:
srand(time(NULL));
rand() % NUM_PORTS; // NUM_PORTS isn't a system #define
Then specify that port in bind. If it fails, pick a new one (no need to re-seed the random generator. If the random port isn't important, look at Remy Lebeau's answer.

Resources