situation: I need to broadcast from client using UDP from some free port, then to accept tcp connection on client from server on the port with the same number, but TCP. That's why I need to listen (and bind) to this port BEFORE broadcasting. The port cannot be const, because I can have multiple clients running on one machine.
So here some questions, which can help me to make this situation clearer:
If I made sendto from unbinded UDP socket, is it binded to any free port and all next sendto messages will go from this port, or each time the port will be chosen for a new message?
Can I ask system to reserve some free port for me? (I need to reserve two ports with the same numbers for UDP and TCP connections)
I'm sure there is a known way to handle these situations, what is it?
1)If I made sendto from unbinded UDP socket, is it binded to any free port and all next sendto messages will go from this port
Yes.
or each time the port will be chosen for a new message?
No.
2) Can I ask system to reserve some free port for me? (I need to reserve two ports with the same numbers for UDP and TCP connections)
That's what happens when the auto-bind occurs. You can do explicitly by binding to port number zero, but it isn't necessary. It also does not guarantee that you can bind both UDP and TCP to the same port number.
3) I'm sure there is a known way to handle these situations, what is it?
You've found it. Let the auto-bind happen.
I've found some answers on stackoverflow
You can bind to 0 port, that is specified it struct semaddr_in. That will allow you get an unused port for your type of connection. It is not defined to be free for other types of connection.
Look at #remy's answer at Bind to any port available
Yes, they can because headers are specified for UDP or TCP protocols. So the machine can tell one from another.
See Can TCP and UDP sockets use the same port?
If you bind to 0 port you'll get ability to listen to it before calling sendto
Related
Hello, 👋
I was wondering how services (like mysql, apache, mongoDB) are bind against a port in the server/local machine. How does this work?
I'm guessing that when the service starts, it tries to connect to the port and if possible, the service is "paused" until the OS receives a request against the selected port. Is there any documentation out explaining how this works?
Thank you!
May I help you?
This is a list of TCP and UDP port numbers used by protocols for operation of network applications.
The Transmission Control Protocol (TCP) and the User Datagram Protocol (UDP) only need one port for duplex, bidirectional traffic. They usually use port numbers that match the services of the corresponding TCP or UDP implementation, if they exist.
I would like to write a daemon that is available on a large number of AF_INET-SOCK_STREAM and AF_INET-SOCK_DGRAM sockets for network debugging purposes.
To avoid excessive resource usage I want to avoid opening a large number of ports on the application layer but try to multiplex the connections per socket type on lower layers.
Knowledge of the original incoming port on the application layer is a requirement.
I have successfully implemented a daemon that listens on an AF_INET SOCK_STREAM socket that is multiplexed by an iptables REDIRECT rule. The original incoming port of the connection can be retrieved by calling getsockopt with SO_ORIGINAL_DST. As I understand this does not work with AF_INET SOCK_DGRAM.
I have also successfully implemented a daemon that listens on an AF_INET SOCK_DGRAM socket that is multiplexed by an iptables TPROXY rule. The original incoming port of the connection can be retrieved by using recvmsg() and consuming the available ancillary message containing information about the connection before multiplexing. As I understand this does not work with AF_INET SOCK_STREAM.
Is there a transport-layer-agnostic way of multiplexing such socket connections and retrieving information about the original incoming port? Possibly even suitable for protocols like SCTP or DCCP?
With TCP you have a connection. The target port for this connection is the same for all packets inside this connection. In this case each connected socket (result from accept) equals to a single connection and the incoming port is a property of this socket. It does not matter in this case if the listening socket will accept connections on multiple ports, all what matters is the connected socket.
With UDP you don't have a connection. Instead the same socket is used to receive packages from multiple clients and in your case to multiple incoming ports. Source and destination IP and port are thus a property of each packet and not of the socket.
That's why you need different interfaces to retrieve the original incoming port: a socket based for TCP and a packet based for UDP.
I ran the command sudo lsof -i -n -P | grep TCP and I was wondering if I could get some more clarification on its output.
Specifically, in this image:
Why do I have an IP:PORT pointing to another IP:PORT and then back at itself with the label 'ESTABLISHED'? I am confused on what this means exactly.
I'm not sure how familiar you are with networking and TCP in general, so I'll try to provide a brief description with a couple of details. From your question, it appears that you're not very familiar with networking internals, so it may be hard to understand some of these concepts, but I hope this helps:
The TCP protocol has various states. Think of it as a state machine. States on the client side include CLOSED, SYN_SENT, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2 and TIME_WAIT.
Thus, the ESTABLISHED label means that the TCP connection is in the ESTABLISHED state. Being in the established state means that both hosts successfully completed the TCP 3-way handshake (and in doing so, transitioned from SYN_SENT to ESTABLISHED). The transition from CLOSED to SYN_SENT happens when the client side sends the TCP SYN request to the server.
In an established connection, both sides transmit and receive application specific data. Basically, a session is established and a bidirectional stream of bytes flows between the two end systems.
TCP sockets are uniquely identified by the 4-tuple (source-ip, source-port, destination-ip, destination-port). The IP identifies an end system's network interface, and the port number is used to multiplex and demultiplex packet arrival at that network interface (so that the target system knows which service to deliver the packets to). That's the meaning of the IP:PORT fields.
I'm not sure why you have two entries for the same connection. This might be system-dependent, although it's odd (in my system I get only one entry per socket). But sockets are bidirectional, so it may be the case that your system shows you each packet flow direction as a distinct entry. This might also depend on how the system implements sockets.
ESTABLISHED means that the TCP connection has completed the 3-way handshake. (Not sure though whether accept must have been called). See TCP state diagram.
Why do I have an IP:PORT pointing to another IP:PORT and then back at itself
That mean you have two TCP sockets open in your process. Most likely, one listens on port 9092, and another one that connected from port 57633 to that listening socket. Port 57633 belongs to the ephemeral port range, i.e. the range of ports that the OS automatically assigns to the sockets that call connect but did not call bind to assign a specific port.
My UDP socket is bind()ing to port 53 (DNS). Does UDP have a TIME_WAIT state or is using SO_REUSEADDR pointless on UDP sockets?
UDP doesn't have connections, so there's nothing analogous to TIME_WAIT. You don't need to use SO_REUSEADDR.
If you're listening on a broadcast or multicast address, you might need to use SO_REUSEPORT, so that if there are multiple listeners on the same machine they don't conflict. However, from what I can tell, this doesn't exist on Linux.
How to open a raw socket for sending from specific TCP port? I want to have all my connections always go from a range of ports below ephemerals.
If you are using raw sockets, then just fill in the correct TCP source port in the packet header.
If, instead, you are using the TCP socket interface (socket(), connect() and friends), then you can set the source port by calling the bind() system call for the client socket - exactly as you would to set the listening port for the server socket.
Making a tcp connection using raw sockets is somewhere between difficult and impossible; you'd need to implement the entire tcp protocol in your program AND also stop the kernel from sending its own replies to the packets (if the kernel has IP bound on that address on that interface).
This is probably not what you want. However, if you did want it, it is trivial to send tcp frames with any source port you want, as you get to specify it in the tcp header, which of course, if you're implementing your own TCP layer, you'll need to understand.