C++ socket connect port assignment issue [duplicate] - linux

When a client connects to a server using TCP, a new socket is created for the TCP stream. Does the connection remain on the same port the connection was made or does it get changed to some other port?

The new socket is an application-level concept introduced because each established connection needs a unique file descriptor (also distinct from the listening file descriptor), which maps to, but isn't the same as, a TCP session. The session itself is identified by the combination of source and destination address and port. The source (client) port is usually chosen at random, while the destination (server) port is the listen port. No additional port is allocated.

The server use the same port to listen and accept new connection, and communicate to the remote client.
Let's me give you an example, (in linux system):
First, start a http server by python:
xiongyu#ubuntu:~$ sudo python -m SimpleHTTPServer 500
Serving HTTP on 0.0.0.0 port 500 ...
Second use nc command to connect to the http server, here we start two client by:
xiongyu#ubuntu:~$ nc 0.0.0.0 500
Use netstat to see the netstate of port 500:
xiongyu#ubuntu:~$ netstat -natp |grep ':500'
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN 54661/python
tcp 0 0 127.0.0.1:51586 127.0.0.1:500 ESTABLISHED 57078/nc
tcp 0 0 127.0.0.1:51584 127.0.0.1:500 ESTABLISHED 54542/nc
tcp 0 0 127.0.0.1:500 127.0.0.1:51586 ESTABLISHED -
tcp 0 0 127.0.0.1:500 127.0.0.1:51584 ESTABLISHED 54661/python
You can see, the http server use port 500 to LISTEN for the client, after a new client connected to the server, it still use the port 500 to communite with the client, but with a new file descriptor .

The socket associated with the new descriptor returned by accept on the server will use the same port on the server side of the connection as the original socket (assuming "normal" definitions where the client initiates the connection). The new socket will have a different client port number (the remote port from the server's point of view).

Related

How does OS route TCP packets of an established connection

I'm confused about how TCP packets are routed on the OS level after TCP connection has been established.
Suppose a sever is listening passively on a TCP port for incoming traffic. The server receives a connection request, accepts it, and created a socket for source_ip:port and destination_ip:port, e.g. (x.x.x.x:9999, 127.0.0.1:8080).
How are subsequent packets sent from x.x.x.x:9999 to 127.0.0.1:8080 routed on the server? Does the OS route them to the process binding port 8080, which in turn routes them to file descriptor with source x.x.x.x:9999? If yes, does this mean that each application much implement logic to route packets of established connections to the appropriate file descriptor?
Or does the OS route them directly to the open socket? If yes, how does the OS know which socket to route to since incoming request use well known port number (8080 in this case)?

How is a TCP mesh network formed

I want to make a mesh network with 3 nodes, like the following:
B connected to A.
B connected to C.
A connected to C.
This is my understanding:
In order for B to connect to A, A will have a TCP server listening on port 8080.
B has a TCP client which will connect to A on 8080.
Now how does A make a connection to C? If C is listening for connections on 8080.
Should every node run both a TCP server and multiple TCP clients to form a mesh?
There is no standard term as TCP server and TCP client, as already hinted in this question's comment section. For reliability purpose, usually we go for TCP protocol as communicating protocol.
The major difference between TCP and UDP is that former is a connection-oriented protocol for communication, whereas the latter is not connection-oriented.
NOTE: I'm going to answer this question without having a background in `node.js`.
In order for B to connect to A, A will have a TCP server listening on
port 8080.
If going for a connection-oriented protocol, A needs to be running a socket application which acts as a server accepting connection requests on port 8080. B will send a connection request to server A.
B has a TCP client which will connect to A on 8080.
Similarly, B needs to have a socket application (client-side) which would send A a communication request on server A's port, i.e., 8080 in this case.
Now how does A make a connection to C. If C is listening for connections on 8080.
Again, considering a connection-oriented protocol, A can distinctly act as a separate client (using the same / different application), which would send connection request to C. For this, again C needs to be running a socket-server application listening on port 8080 so that A can send a connect request.

How does webserver handle multiple connections on the same port [duplicate]

This question already has answers here:
TCP: can two different sockets share a port?
(7 answers)
Closed 6 years ago.
TCP connection is defined by [client IP address:outgoing port - server IP address:incoming port]. Web server listens on one port but handles multiple tcp connections on the same port - how is that achieved? Is one connection somehow transferred to other incoming port to be able to listen to new connection?
Even if the server IP and server port are the same, the client IP or client port are different. So there is no problem, from the TCP point of view.
If you want more details, in the server code there is a socket destined to accept connections, that will be the listening socket and it will be bound to the server port (and optionally to the IP). When a client connects to this port the listening socket accepts it and a new connected socket is returned.
Even if all the server sockets use the same port, only one of them is actually listening, so there is no problem.

Linux/Unix Socket Self-connection

When a client try to connect to a server, if client and server are both localhost, self-connection may happen(source port and destination port happened to be the same.). But my problem is, client is not listening to that port, how can self-connection be possible?
I found your question after encountering the same phenomenon. The best explanation I found is at Everything About Nothing: TCP Client Self Connect.
You can ask for the port assigned to you via getsockname() and compare it to the remote port to detect these self connections:
sockaddr_in addr_client;
socklet_t len = sizeof(saddr_in);
if(getsockname(sock_client, (struct sockaddr *)&addr_client, &len))
{ /* error */ }
if(len != sizeof(saddr_in)))
{ /* error */ }
if(addr_client.sin_port == addr_server.sin_port &&
addr_client.sin_addr.s_addr == addr_server.addr.sin_addr.s_addr)
{ /* self-connection detected! */ }
The server and client in localhost don't use the same port.
As a connected Tcp connection,
To server,source port is A and destination port is B.
To client,source port is B and destination port is A.
A is set by bind() in server, and is known to all clinets; B is usually assigned by clinets' kernel, and is known to server when the server's accept() returns.
In details:
In tcp,the server's port is set by bind() which lets us specify a port number, an IP address, both, or neither, but it is rare for a TCP server to let the kernel choose an ephemeral port Afterwards, server listen() the port and IP address.
and client uses connect() whose socket address structure must contain the IP address and port number of the server. the kernel will choose both an ephemeral port and the source IP address if necessary. Anyway, it can't be the port your server using.
That's to say, the ports of a server and a clinet in the same computer is not the same.
For example, when simple C/S programs running in a localhost, typing netstat -t in terminal,and you will get:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:41742 localhost:9877 ESTABLISHED
tcp 0 0 localhost:9877 localhost:41742 ESTABLISHED
the prots is obviously different.
If you force the client to use the same port of your the one server is using on local by bind(), the bind() will return -1 as a error.
We can simple reproduce this phenomenon with the following python program
import socket
for i in range(65536):
try:
s = socket.create_connection(('127.0.0.1', 50000))
print 'connected to {0}'.format(s.getpeername())
except Exception as e:
pass
when we try to connect some socket in the same host. if we don't bind your client to a specific port, operating system will provide ephemeral port for you. if it's happened to be the one you want to connect to. it causes self connection. Make sure the port you are trying to connect is in /proc/sys/net/ipv4/ip_local_port_range

How can i externally connect to a service running on 127.0.0.1 (rather than 0.0.0.0)?

I'm trying to connect to a service, and to debug it, I ran
netstat -nap | grep LISTEN
The results should rows of two types :
tcp 0 0 127.0.0.1:8020 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:57140 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:11000 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN
unix 2 [ ACC ] STREAM LISTENING 4512 -
unix 2 [ ACC ] STREAM LISTENING 9760 -
I have 3 questions :
1) I want to connect to the process running on 127.0.0.1 --- how can I do this externally ? I have read elsewhere that 127.0.0.1 processes are only allowed to communicate with other localhost processes.
2) What is the difference between the "tcp 0" netstat records and the "unix 2" ones ? Im somewhat naive about networking, so feel free to overexplain this one :)
In short, your process is bound to a loopback interface which cannot receive packets from an external network. You'll need to reconfigure the process bound to port 8020 to bind to an external interface to be able to connect to it from another host.
The long answer is that the two addresses you site (127.0.0.1 and 0.0.0.0) are both special in certain ways, and it is useful to understand what you're seeing.
Addresses in the 127.0.0.0/8 Internet Protocol address block (of which 127.0.0.1 is one) are reserved for use internally on a host. See rfc5735 for details, but there's nothing special about these addresses except that all IP hosts use the same rules and aren't setup to route these addresses outside a host or router.
On your computer, you'll usually see a special "loopback" network interface that has 127.0.0.1 assigned.
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
This interface is special and never connected to an external network. It is used when a program wants to connect to a service on the local machine as 127.0.0.1 will almost always be configured as an active network interface. Packets will only arrive on this interface if they are sent from a local process.
The other address you site, 0.0.0.0 is special and usually represents all IP addresses mapped to any network interface on your computer. When a program wants to listen for connections arriving on any network interface or IP address, it will bind a TCP/UDP port to 0.0.0.0 to listen for connections.
In your case, however, you're reporting netstat output listing 0.0.0.0 on lines describing TCP sockets in a LISTEN state. In this case, netstat is listing sockets listening for connections and using 0.0.0.0:* as a place holder for the foreign address field of it's output. In this case, 0.0.0.0:* signifies that the socket is waiting for a connection from any host.
Regarding your question on "tcp 0" vs. "unix 2", these are the first two columns of your netstat output. A look at the column headers from your netstat command is useful:
# netstat -nap | head -2
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
What you're reporting as "tcp 0" simply means a socket using the TCP protocol has zero bytes in the received queue waiting for the program connected to this socket to consume. Similarly, "unix 2" is what's called a unix socket with two bytes waiting in its receive queue for the connected process to consume.
TCP sockets are part of the TCP/IP stack that can be used locally or across IP networks for processes to communicate. UNIX sockets, on the other hand, are simpler and only used for what's called IPC or inter-process communication which only happens between two processes both running on the local system, and there's no networking involved (no addresses and ports anyway). UNIX sockets are considered to be more efficient than TCP sockets, but they are obviously more limited in function. On UNIX-like systems UNIX sockets are implemented as a file on the file system of a special "socket" type that both processes using the socket read and write to as a communication channel.
1) Without binding it to 0.0.0.0, you can still access the service through a tunnel. This is similar to using a proxy as David Schwartz mentioned. There's a few assumptions I'm making for this example:
The server is running a service bound to 127.0.0.1:8020, we'll call it 'myservice'.
The server is running OpenSSH server 'sshd' on the default port of TCP 22, and the user can log in with the username 'myusername'.
The client is running a system with OpenSSH client installed.
The server is accessible via the IP address of 10.20.30.40.
On the client, SSH to the server with the following command:
ssh -L 12345:localhost:8020 myusername#10.20.30.40
Once you log in, minimize the SSH window. In another window on the client, run netstat to find listening ports. You should see 127.0.0.1:12345, just like on the server.
On the client, connect to the service on 127.0.0.1:12345. You should now be connected to the 'myservice' instance on the server, even though you made the connection to the client's local loopback interface.
The trick here is that SSH is tunneling a listening socket on the client to the listening socket on the server. I've made the port numbers different for clarity.
1) You would either need to modify the server to bind to a publicly accessible address (or 0.0.0.0) or run a local proxy to handle the connection.
2) TCP connections use the TCP protocol, the one used for connection-oriented traffic on the Internet. UNIX connections use a strictly local protocol that is much simpler than TCP (because it doesn't have to deal with dropped packets, lost routes, corrupted data, out of order packets, and so on).
1) You cannot (if you mean from another machine - 127.0.0.1 is localhost and by definition you can only connect to it from the local machine
2) The first column shows the domain of the sockets - tcp are tcp sockets and unix are unix domain sockets.
And as for the answer to you question 3 ;-)
3) 42

Resources