How many sockets are needed per connection? - c++

Say we have a server program with socket sa and new_socket. The tutorial I'm using takes socket sa and new_socket, and two structures of sockaddr_in named server and client; then binds the socket to an IP address:port, then calls listen() function. When listen returns, the program calls
new_socket = accept(sa, (struct sockaddr*)&client, &length);
My question is, lets say there are 3 people connecting...
Do I need to have 3 different structs and 3 different new_sockets for each accept function, say if i want my server to serve 3 different clients connecting to it?
Also, why do we need a new_socket for accept? Why is there two different sockets 1 for bind and 1 for accept? Shouldn't socket operations be performed on the binded one?
I'm trying to implement a class for sockets to make it easier on me, and as a good way to practice my oop skills....

You need one socket for the server in general. This socket is where you set the port that the server is listening on, and call accept() to wait for incoming connections.
In addition, you need a socket for each client connection. This is a new socket that is returned by accept(). This is necessary because a server can handle multiple clients. If you used one socket for everything, there would be no way to tell which client was sending you a message, or indicate which client to send a reply to.

Related

Can a tcp client use the same port to a different Server?

I want to write a tcp server and client application, which has several different connections to each other where the client uses the same port number.
So far I understand it, the server has a listener port and when the client calls it, then I get a new socket for this new connection on the server side, when I call
accept();
Right? So on Server side I can identify my connection with this new socket and send data through it.
Now my understanding problem with the client side. There I get my socket when I call
socket(AF_INET, SOCK_STREAM, 0)
so I have only one socket. In the
connect()
I can specify remote adress and so on. So when I understand it correctly I can use one socket to make several connects to different adresses/port pairs to create different connections. Right?
But how can I now see in the Client from which logical connection I receive my data or how can I send it when 2 logical connections use the same local port at the client? On serverside I have 2 sockets when I have 2 accept called but what about the client side? For send and receive I have only one socket handle?
Or do I have to call socket() for each logical connection on the client?
I can specify remote adress and so on. So when I understand it correctly I can use one socket to make several connects to different adresses/port pairs to create different connections. Right?
No. A socket is the combination of IP address plus port number.
Or do I have to call socket() for each logical connection on the client?
Yes.
It seems to me your confusion arises because you think for example that a certain port is used for SMTP connections and a certain port is used for HTTP connections.
Well, that port alone is NOT defining for you a socket to the server. The IP address of the server is changing.
As an example, consider the following scenario:
You want to connection to Stackoverflow:
Your PC – IP1+port 50500 ——– Stackoverflow IP2 + port 80 (standard http port)
That is the combination IP1+50500 = the socket on the client computer and IP2 + port 80 = destination socket on the Stackoverflow server.
Now you want to connect to gnu.org:
your PC – IP1+port 50501 ——–gnu.org IP3 +port 80 (standard http port)
The combination IP1+50501 = the socket on the client computer and IP3 + port 80 = destination socket on the gnu.org server.
Better check out Beej's Network Programming to learn more. It is a must-read for anyone working with sockets.
So when I understand it correctly I can use one socket to make several connects to different adresses/port pairs to create different connections. Right?
No. A TCP socket can only be used once. When its connection has finished, or even if connect() just fails to make a connection, you must close the socket and create a new one if you want to make a new connection.
But how can I now see in the Client from which logical connection I receive my data or how can I send it when 2 logical connections use the same local port at the client?
Every TCP connection will have its own unique socket allocated for it. It is your responsibility to keep track of them.
On serverside I have 2 sockets when I have 2 accept called but what about the client side?
The exact same thing happens on the client side, too. You need to create and connect a separate socket for every TCP connection you make. So, you will have a new pair of socket()/connect() calls for every connection.
For send and receive I have only one socket handle?
No, you will have a separate socket for each connection, just like on the server side.
Or do I have to call socket() for each logical connection on the client?
Yes, and connect(), too.
I will not talk about a specific programming language rather I will give a general answer that is applicable for all:
In networking what you care about is the socket (IP+Port) this should be unique whether it is server/client socket or UDP/TCP socket.
For server sockets you must assign a port. For client sockets usually you do not specifically assign a port but it will be assigned by the operating system automatically. However, you can still assign a port to a client socket manually (e.g. in case some port numbers are blocked by the firewall)
In the server process:
you can get the server socket info and the connected client socket info
In the client process:
you can get the client socket info and the server (you want to connect to) socket info (of course you should know the server socket info previously otherwise how will you connect to it).
You can send/receive from/to client sockets. After the server gets the connected client socket it can send/receive through it. Same for the client side it can send/receive through its socket.
The "socket" abstraction is an unfortunate relic of past network stack design. It mixes two different sorts of objects.
A listening socket on the server has a port, and potentially an IP address of the local interface. However, this can also be 0.0.0.0 when listening on all interfaces.
A connected socket is associated with a TCP connection, and therefore has 4 parameters: {local IP, local port, remote IP, remote port}.
Now on the client side, you typically don't care about local IP or local port, so these are locally assigned on connect. And yes, these local parameters can in fact be reused for multiple connections. Only the 4-tuple of {local IP, local port, remote IP, remote port} needs to be unique. The OS will map that unique tuple to your SOCKET.
But since you need a new 4-tuple for every connection, it also follows you need a new SOCKET on both sides, for every connection, on both client and server.

Winsock: Listen and recv (differences)

I found this defeinitons of funcion listen and recv in winsock library (TCP/IP stream communication).
The listen function places a socket in a state in which it is listening for an incoming connection.
The recv function receives data from a connected socket or a bound connectionless socket.
Does it mean that if I want to receive data from particular socket I should firstly use listen and then recv? I'm not sure if I understand this correctly.
The functions listen and recv have quite different functionalities and uses.
The listen function is designed to allow a server awaiting the connection of one or more clients to listen on a port for if anyone connects.
The recv function is used on an already established socket to receive data which has been sent from the machine at the other end of that socket.
As it has been mentioned in comments, I shall also mention connect. Connect is the counterpart of listen. It talks to the port which a listening machine is listening on and establishes a socket with that machine.
what the BSD socket and winsock libraries don't really make clear is that from a programmers perspective there are two quite different kinds of socket, a listening socket and an established one.
A server will first need to create a listen socket with which it waits for clients, this socket is not used for actually sending any data, it only exists in order to aid the creation of an established socket. However the listening socket does not become the established socket, when a client connects, the listen socket actually creates a second socket for the data transfer.
The established socket is the kind we recognise and use for most things. It is a socket with machines at both ends, listening and sending to perform data transfer.

Winsock ~ Creating an UDP Listener (Multiple vs 1 socket)

Dear Stackoverflowers,
I am researching networking a bit and I decided I'd like to create a small and simple networking library with Winsock. (I am using Completion Ports and Overlapped IO though)
As I researched a bit I came to the following steps for a TCP Listener(Correct me if I am wrong):
Create a Listening Socket
Bind it to a port/IP
Listen on it
When a new connection is created, give a seperate Socket for that connection.
Listener continue's to listen, the specific connection is handled as needed.
EDIT: With a 'connection' from here I mean communication between the server and distinct clients.
Though for an UDP Listener we need to make use of WSARecvFrom which returns the IP address at the lpFrom parameter. Now I was wondering the following:
Is it better to make one UDP Socket listen to incoming connections on a specific port with WSARecvFrom and create new sockets for every specific connection? Or could I just use the UDP Socket itself with WSASendTo. Would that cause any performance penalties if one UDP Socket is used for for example 1000 connections? Or would it be the same or even better then creating/duplicating seperate Sockets for each different incoming connection?
Note: If multiple sockets are needed how would you handle sockets listening on the same port or could a client accept UDP from different ports?
Hope you guys can help!
Ps. Extra tips are always welcome!
Unlike TCP, UDP is connection-less, and as such you don't need to create separate sockets for each party. One UDP socket can handle everything. Bind it to a local IP/Port and call WSARecvFrom() once, and when it reports data to your IOCP you can process the data as needed (if another thread if needed) and then call WSARecvFrom() again. Each time new data arrives, you have to look at the reported lpFrom address to know the IP/Port of the sender. And yes, you can use the same UDP socket for sending data to each sender when needed.

Boost.Asio datagram (UDP) socket that is both bound and connected

I have problems understanding the concept behind Boost.Asio's (using v1.49.0) boost::asio::ip::udp::socket sockets.
First I am gonna to to explain what I want to achieve:
I hide the Boost.Asio sockets behind a very simple interface (Pure Abstract Base Class), so I have two wrapper classes that allow to access either a stream socket or a datagram socket.
I want to configure both the local endpoint and the remote endpoint before passing the Boost.Asio socket to the constructor of my wrapper class.
I want to use the socket.receive (alternatively boost::asio::read) and socket.send (alternatively boost::asio::write) member functions instead of the socket.receive_from and socket.send_to member functions.
The only way to use socket.send and socket.receive with a boost::asio::ip::udp::socket seems to connect the socket.
A UDP socket can both be bound and connected:
Binding is achieved via the socket.bind member function.
Connecting is achieved via the socket.connect member function.
The problem is, that even though I am able to
Open the socket,
Set socket options,
Bind the socket,
Connect the socket,
and to be able to send data via the socket, I can not receive data from the socket. If I don't connect the socket, I can receive data via the bound local endpoint, but I am unable to send data with the approached described.
So my central question is: Am I trying something that is impossible to achieve?
Can I only use bind or connect with one socket instance?
If the answer to the two previous questions is no: What do I have to do, to be able to receive and send data via a bound and connected Boost.Asio UDP socket.
I know that UDP is in fact connectionless, therefore the text uses Boost.Asio terminology. I have also read connect on "connection less" boost::asio::ip::udp::socket which seems to indicate that it is impossible what I am trying.
You are missing one point from man page ofconnect:
If the socket sockfd is of type SOCK_DGRAM, then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.
This means, that if you want to connect the socket, then it will be able to receive datagrams only from remote endpoint (the connected one), i.e. peer will have to bind own socket before sending datagram to your socket waiting for data.
If you need to received data from more than one peer, you can connect udp socket to "any" address (i.e. 0.0.0.0 - udp::v4()) and some port.

udp socket with c++ and windows API

I'm writting an UDP server for a game.
Do you know if is possible to have multisocket in UDP on one port ? or I must use dynamic port (one socket = one port) ?
thanks
It make no large sense to create multiple socket on one UDP port. UDP is not point 2 point protocol like TCP so using one "server" socket bind to specific port you can handle hundreds of clients.
See Using SO_REUSEADDR...:
Using SO_REUSEADDR
The SO_REUSEADDR socket option allows a socket to forcibly bind to a
port in use by another socket. The second socket calls setsockopt with
the optname parameter set to SO_REUSEADDR and the optval parameter set
to a boolean value of TRUE before calling bind on the same port as the
original socket. Once the second socket has successfully bound, the
behavior for all sockets bound to that port is indeterminate. For
example, if all of the sockets on the same port provide TCP service,
any incoming TCP connection requests over the port cannot be
guaranteed to be handled by the correct socket — the behavior is
non-deterministic. A malicious program can use SO_REUSEADDR to
forcibly bind sockets already in use for standard network protocol
services in order to deny access to those service. No special
privileges are required to use this option.
Bonus reading: What exactly does SO_REUSEADDR do? .
Sure you can have multiple UDP sockets on one port if SO_REUSEADDR is specified via setsockopt.
However, I doubt that what you really need is using one UDP socket to communicate with multiple clients, which is also feasible. UDP is not connection-oriented, UDP APIs like sendto and recvfrom could distinguish different peers on one socket.