I've recently started to learn about socket usage, more specifically in Java.
In this link is shown a simple client-server UDP application.
My question is: How does the client receives the response with receive() method when this datagramsocket object calling receive doesn't have a port set?
The client initializes its DatagramSocket via the nullary constructor, which binds the socket to some available port (chosen in an unspecified manner) on the wildcard address. That's quite different from not having a port set -- there is a port set, but it is chosen by the computer, not explicitly specified by the program.
When the server receives a message, it extracts not only the message data, but also the source address and port. It sends its response to that address and port. The client successfully receives it via the same socket with which it sent the original message, because it's still bound to the same port, even if you don't know exactly which one that is.
the first time you send a packet using that socket, an ephemeral port will be allocated. If you need a specific port then you can bind it explicitly which is needed for bootp for instance. But in the most simple case bind is not needed and you get the ephemeral port.
The peer will see this port in the UDP header because in there is both the source and destination port.
As a side note this mechanism is the same for TCP clients. When they do a call to connect() unless the socket was bind to a specific port, an ephemeral port will be allocated by the clients kernel and that one will be used for the lifetime of the connection.
The ephemeral ports are usually in a specific range, there is kindof a pool of ports for UDP and TCP. The kernel usually has a mechanism to take from the pool starting from the beginning and gradually incrementing till the end is reached upon which he'll start from the beginning. Skipping ports that are still in use of course. It is called the ephemeral port range, and it is specific to the os.
how to change/view ephemeral port range in windows machines
Related
I've been reading this socket tutorial by Oracle and stumbled upon the following text:
If everything goes well, the server accepts the connection. Upon acceptance, the server gets a new socket bound to the same local port and also has its remote endpoint set to the address and port of the client. It needs a new socket so that it can continue to listen to the original socket for connection requests while tending to the needs of the connected client.
Now if I'm not wrong then the port size is 16 bit which limits the max no of ports around 65K. This means that a server can't handle more than 65535 connections at any instant if all of it's port are bound to some client local port. While some answers like this on stackoverflow suggest that there's no limit on active connections. What is true about this and what is wrong?
Edit 1: If indeed a server can't handle more than 2^16-1 connections, then how do websites like Google handle this limitation?
A unique TCP connection is defined by a unique combination of client IP, client port, server IP and server port. For a specific service server IP and port are constant (i.e. port 80 for HTTP), but client IP and port can vary. Since the port range is only 1..65535 this means that the server can only handle at most 65535 different connections from the same client IP address at the same time, because these are all possible unique combinations of the connection tuple when only the port can be changed. But, if there are multiple clients with different IP addresses this limitations applies to each of these clients separately. If you then look at the amount of different possible IP addresses (IPv4 and IPv6) you'll see that there is essentially no real limit of how much connections the server could handle in theory.
In practice each of these TCP connections takes memory at the server since the current state has to be kept. Additional memory is needed in kernel and application for file descriptor and application protocol state etc. This means that there is a practical limit based on the resources of the machine which might be less then 64k but also way more, depending on the system and its configuration.
They use something like NAT (network address translation) for your ISP.
You can access different computer behind your router because your router maps the routes to the PCs internally.
E.g. Google data center does the same thing. Mapping "Google.com" to different internal server allowing them to accept more than 65k connections in total.
I've seen many answers similar to this one in regards to serversockets in java: "Let's say you have a server with a serversocket on port 5000. Client A and Client B will be connecting to our server.
Client A sends out a request to the Server on port 5000. The port on Client A's side is chosen by the Operating System. Usually, the OS picks the next port that is available. The starting point for this search is the previously-used port number + 1 (so for instance if the OS happened to us port 45546 recently, the OS would then try 45547).
Assuming there are no connection problems, the Server receives Client A's request to connect on port 5000. The Server then opens up its own next available port, and sends that to the client. Here, Client A connects to the new port, and the server now has port 5000 available again."
I've seen answers like this in multiple questions on stackoverflow about how a different port is used in the returned socket of the accept() than the port that the ServerSocket is listening on. I was always under the impression that TCP is identified by the quartet of information:
Client IP : Client Port and Server IP : Server Port ->protocol too (to distinguish TCP from UDP)
So why would the accept() need to return a socket bound to a different port? Doesn't the quartet of information sent in every header distinguish multiple connections to the same server port from different machines enough where it would not need to use different ports on the server machine for communication?
The Server then opens up its own next available port, and sends that to the client.
No. It creates a new socket with the same local port number. No second port number is allocated or sent to the client. The SYN/ACK segment which is the server's response to the connect request does not contain a second port number.
Here, Client A connects to the new port,
No. The client acknowledges the SYN/ACK packet and the client is connected to the original port from then on, after acknowledging the SYN/ACK. There is no second connect.
and the server now has port 5000 available again."
It always did.
I've seen answers like this in multiple questions on stackoverflow about how a different port is used in the returned socket of the accept() than the port that the ServerSocket is listening on.
Any such answer is incorrect and should be downvoted 'with extreme prejudice' and commented on adversely. The TCP handshake is defined in RFC 793 and does not specify allocation and exchange of a second port and a second connect message. There are only three messages, which isn't even enough for that to occur.
So why would the accept() need to return a socket bound to a different port?
It doesn't.
Doesn't the quartet of information sent in every header distinguish multiple connections to the same server port from different machines enough where it would not need to use different ports on the server machine for communication?
Yes.
You are correct in the TCP packet header's information. It contains:
Client IP | Client Port | Server IP | Server Port | Protocol
Or, more appropriately (since client/server become confusing when you think about bi-directional transfer):
Source IP | Source Port | Destination IP | Destination Port | Protocol
Multiple connections to the same server port will come from different ports on the client. An example may be:
0.0.0.0:45000 -> 1.1.1.1:80
0.0.0.0:45001 -> 1.1.1.1:80
The difference in client ports is enough to disambiguate the two sockets, and thus have two separate connections. There is no need for the server to open another socket on another port. It does receive a socket from the accept method, but it's assigned to the same port and is now a route back to the newly accepted client.
FTP, on the other hand, does have a model where the server will open a new unprivileged port (> 1023) and send that back to the client for the client to connect to (this is referred to as "Passive FTP"). This is to resolve issues where the client is behind a firewall and can't accept incoming data connections from the server. However, this is not the case in a typical HTTP server (or any other standard socket implementation). It's functionality that is layered on top of FTP.
I want to create a three way communication system in which every party has equal rights, with two communication channels to his partners.
The program is decentralized and every machine runs the same code, in which there is a list of three IP addresses, with every one representing one of the machines. For each machine the partners' IP addresses are determined by looking at it's own IP address and using the other two from the list.
Now there is no predetermined order in which the machines are being turned on, is there any way to control the TCP communication other than setting it something like
'if the IP address you want to speak to is higher than your own, connect to a server, otherwise you are the server and accept sockets'?
In the end I want a TCPread(port) which fires every time a message from any IP comes in and a TCPwrite(port, ip, message) which sents a message.
My idea was a TCPhandler which stores all sockets it's got for every port I plan on using in the programm with one thread per port. Then everytime a read or write is performed it checks if there is a socket for the port and IP address in the handler, if not it sends a socket to the IP and waits for a response... I don't think i've understood that whole TCP thing entirely though.
If you don't care about number of connections you can do following:
Each peer open port and listen for incoming connections
Try to establish connections to each peer with some period of time
As result you will get two connection between each peer. Now you can use them following way:
Outgoing connections are used for sending messages
Incoming connections are used for receiving messages
In the server side, i use this code :
ServerSocket server = new ServerSocket(1234);
Socket server_socket = server.accept();
I found the server is listening on port 1234.
When one or more client sockets are connected, they are all using the same port 1234 !
That is really confusing :
I remember that multi sockets can't use the same port, isn't it right ? Thanks.
A TCP connection is identified by four numbers:
client (or peer 1) IP
server (or peer 2) IP
client port
server port
A typical TCP connection is open as follows:
The client IP is given by the client's ISP or NAT.
The server IP is given by the user or looked up in a DNS.
The client chooses a port arbitrarily from the unassigned range (while avoiding duplicate quadruples)
The server port is given by the protocol or explicitly.
The port that you specify in the ServerSocket is the one the clients connect to. It's nothing more than a port number that the OS knows that belongs to your application and an object that passes the events from the OS to your application.
The ServerSocket#accept method returns a Socket. A Socket is an object that wraps a single TCP connection. That is, the client IP, the server IP, the client TCP port and the server TCP port (and some methods to pass the associated data around)
The first TCP packet that the client sends must contain the server port that your app listens on, otherwise the operating system wouldn't know what application the connection belongs to.
Further on, there is no incentive to switch the server TCP port to another number. It doesn't help the server machine OR the client machine, it needs some overhead to perform (you need to send the new and the old TCP port together), and there's additional overhead, since the server OS can no longer identify the application by a single port - it needs to associate the application with all server ports it uses (the clients still needs to do it, but a typical client has less connections than a typical server)
What you see is
two inbound connections, belonging to the server (local port:1234). Each has its own Socket in the server application.
two outbound connections, belonging to the client (remote port:1234). Each has its own Socket in the client application.
one listening connection, belonging to the server. This corresponds to the single ServerSocket that accepts connections.
Since they are loopback connections, you can see both endpoints mixed together on a single machine. You can also see two distinct client ports (52506 and 52511), both on the local side and on the remote side.
Well, i am at new at Socket programming in java. I tried to implement a simple socket program to send the message with 127.0.0.1:4242 as localhost. But i want to send message to specific IP. How can i achieve that? Will it be possible to send message to my own IP as client-server running simultaneously?
An endpoint in socket communications is an endpoint. Anything you can do using 127.0.0.1 can be done using that machines ip address. See here for more details.
Every IP datagram has a source address and a destination address in the IP header, plus a transport protocol number, which is for majority of Internet traffic is either TCP or UDP. Then the header for that transport protocol lists source and destination port numbers.
So here you have it - sending, or better said "client", application gets assigned source address and port, usually automatically - address determined by the local routing table, port number assigned out of range of ephemeral ports, while "server" application listens on a well known port bound to an address at a particular machine. This tuple (source IP, source port, destination IP, destination port) is enough for the datagram to get from here to there.
127.0.0.1, and actually all the addresses in the range 127/8, are reserved for the loopback, a virtual local interface, i.e. it's the way to say "no matter what my real address is, or even if I don't have one, connect to this machine I'm at right now".
Read up on the TCP/IP suite of protocols - it's a fairly simple concept (with ton of interesting details, of cource).