What things are exactly happening when server socket accept client sockets?

When you create a socket and do a bind on that socket and then a listen, what you have is what is called a listening socket. When a connection is establised this socket is basically cloned to a new socket, and this socket is called the servicing socket the port to which it bound is still the same as the original port.

But there is an important distinction between this socket and the listening socket from before. Namely it is part of a socket pair. It is the socket pair that uniquely identifies the connection. so as there are 2 sockets in the picture for a socket pair, there are 2 IP adresses and 2 ports for both ends of the TCP communication channel. During the cloning of the servicing socket, the TCP kernel will allocate what is called a TCB and in it it will store those 2 IP@ and 2 ports. The TCB also contains the socket number that belongs to the TCB.

Each time a TCP segment comes in , the TCP header is checked and whether or not it is a SYN, for a SYN you would have connection establishment so that you passed already, but then the kernel is going through its list of listening sockets. If it is a normal TCP packet, not a SYN, both port numbers are in the TCP header and the IP@ are part of the IP header, so using this information the kernel is able to find the TCP that belongs to this TCP connection. (For a SYN, this information is also there, but as I said, for a SYN you have to process only the listening sockets)

That is in a nutshell how it works.

This information can be found in UNIX Network Programming: the sockets networking API. In there the link to the sockets is described whereas in other reference material it is usually not described that much in detail, rather the nitty grits of TCP are usually highlighted.


When server socket do accept(), it creates a new (client) socket that is bind to port that is different from the port server socket is bind. So socket communication is done via newly bind port, and server socket (for accept() only) is waiting for another client connection on originally bind port.

No.

I think this is not quite proper answer

It is a wrong answer.

because (1) port matches to a single process

That doesn't mean anything relevant.

and (2) socket accept is inside-process matters

Nor does that. It doesn't appear to mean anything at all actually.

and single process can have multiple sockets.

That's true but it doesn't have any bearing on why your answer is wrong. The reason your answer is wrong is because no second port is used.

When server socket do accept(), it creates a new (client) socket that is not bind to any specific port

No. It creates a second socket that inherits everything from the server socket: port number, buffer sizes, socket options, ... everything except the file descriptor and the LISTENING state, and maybe I forgot something else. It then sets the remote IP:port of the socket to that of the client and puts the socket into ESTABLISHED state.

and when client communicates with the server

The client has already communicated with the server. That's why we are creating this socket.

it uses the port that is bind to server socket (who accept()s connections) and which client socket to actually communicate is resolved by (sourceIP, sourcePort, destIP, destPort) tuple from TCP header(?) at Transmission level

This has already happened.

This is also suspicious because I thought socket is somewhat application-level object)

No it isn't. A socket is a kernel-level object with an application-level file descriptor to identity it.

If the socket communications still use server socket's port, i.e. client sends some messages to server socket port, doesn't it uses server socket's backlog queue?

No. The backlog queue is for incoming connect requests, not for data. Incoming data goes into the socket receive buffer.

I mean, how can messages from client be distinguished between connect() and read() or write()?

Because a connect() request sets special bits in the TCP header. The final part of it can be combined with data.

And how can they be resolved to each client sockets in server, WITHOUT any port binding?

Port binding happens the moment the socket is created in the call to accept(). You invented this difficulty yourself. It isn't real.

If one of my scenario is correct, would answer to the questions following?

Neither of them is correct.

Or possibly I'm making two wrong scenarios, so it would be very thankful for you to provide right answers, or at least some relevant texts to study.

Surely you already have relevant texts to study? If you don't, you should read RFC 793 or W.R. Stevens, TCP/IP Illustrated, volume I, relevant chapters. You have several major misunderstandings here.


From the Linux programmer's manual, as found via man 2 accept. Link

The accept() system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket sockfd is unaffected by this call.

So what happens is that you have a listening TCP socket. Someone requests to connect().

You then call accept(). The old listening socket remains in listening mode, while a new socket is created in connected mode. Port is the original listening port.

That does not interfere with the listening socket, because the new socket does not listen for incoming connections.

Tags:

Sockets

Tcp