Java multiple connection to server in dynamic ports - java

I need to have a UDP server which allow me to receive/send informations from/to clients which dynamically will open a socket with a free port (so it will be differente from device and device). The client will send and receive in the same port, so the server must be able to communicate with it.
how could I set the server to stay open in every port? if I had 250 thousand users how could I handle them without tails problem and preventing the port to be occupied from another client?
I thought about open every port with different sockets in a different thread, but I don't know if this is a correct way.

A UDP Server can listen and be open on only one port. All clients can send data to that port. The server will have to handle each data and respond if needed to the peer who sent its data. This should happen even if more than one client wish to send data to server. In UDP context one client will not hog the server port.(Unless the application is badly written).

Related

Can we create two sockets with same portnumber

I am trying to create a client-server model using socket programming in Java. I have multiple clients connecting to a server socket, but once the connection is lost, I need to reconnect to the server but using the same port number for the client. I have data stored on the server with respect to the port number through which it came. Is it possible to get the same port number for a socket again?
The server has no control over which port a client connects from.
On the client side, however, a socket can be bind()'ed to a specific local IP/Port before it is then connect()'ed to the server. Just note that it may take some time for the OS to release the port from the previous connection before it can be reused again. And also, if the client has to connect through a proxy/router to reach the server, the IP the server sees will be the proxy/router's IP, not the client's IP, and there is no guarantee that the port which the server sees will be the same port which the client is using.
The real question is, why are you relying on something unreliable like a client ip/port to store your data? I would suggest using a unique ID to identify the data, like say a user login, or a server-generated ID that is given to the client. If the client disconnects and reconnect, it can just login/send back the same ID.

what to use for identifying between clients that connect to a server? Java, Android, Sockets

I am working with a Java desktop server and multiple Android clients connected to it. on the server side I need to identify which client has sent me a message by sockets TCP/IP and send a response only to that one client and not the others.
I will store all the sockets of clients in an ArrayList.
first here are two ways that I tried that don't work;
-- the IP address of the client, get this by calling socket.getLocalSocketAddress() in the client and socket.getRemoteSocketAddress() in the server, but they never match. for example i got in the client XXX.XXX.11.17 and in the server XXX.XXX.0.13, they are supposed to be the same for the same connection.
-- the port number, get this by calling getLocalPort() in the client and getPort() in the server, yes this works perfectly and the numbers match so I can use this, HOWEVER there is a possibility that the randomly selected port numbers on two different clients could be the same. not likely but possible. so that means there is no guarentee that they are unique.
what is the alternative that I can use that will work?
I need to identify which client has sent me a message by sockets TCP/IP and send a response only to that one client and not the others.
Send it back down the same socket you received the request from.
If you need a permanent identified for the client, you can use the result of Socket.getRemoteAddress().
getLocalSocketAddress() in the client and getRemoteSocketAddress() in the server [...] are supposed to be the same for the same connection.
No, because you don't know what's in between. Most mobile providers use proxies, NAT and so on. The mobile device thinks it's on a LAN (10.0.0.x or 192.168.x.x addresses) which the provider provides. It's even possible for multiple clients to have the same remote address (as seen from your server).
That being said, you can uniquely identify a client in your server application by the remote IP address and port combined together, given the server listens on one IP, port and protocol. This information is available from socket.getRemoteSocketAddress(), where the returned InetSocketAddress (in case of an internet socket) contains both the remote IP and port (getAddress() and getPort() respectively).
But as indicated by the other answer, you don't really need a way to identify a client. A network client is identified by the socket you receive data on (a socket is an exclusive connection between two nodes), so just send the data back to the socket that you received the request on.
If you do need more bookkeeping data about the connected client, wrap the client socket in a wrapper class that contains additional information.

How to find instances of active servers on the local network?

I have a spreadsheet application in Java, and one of the features it provides (which I developed) is sheet sharing. Basically, anyone can be a client or a server because the app has both server and client code. The user who is the server creates the share, specifies the IP, and then the share is created and active (best case scenario) with the server listening for clients on its IP and selected port.
At the moment, the client needs to enter the IP and port of the server that's listening in order to connect. The server then creates a new socket for that client and communicates with in on a separate thread, while the server continues listening on another (traditional TCP behavior). This is all working fine.
What I need to develop is auto-discovery, e.g. a client does not need to type in an IP or port, they simply select 'Join a share...' from the menu and then it starts looking for servers. When one is found, it should send its list of active shares on that IP. The user then selects which share to join from the list, and is connected.
However, I have doubts on how to tackle this issue. Should I use broadcast to poll servers, like DHCP does? Or is there an easier way?
What I'd like to implement is:
Client -> polls local network -> finds a server -> server sends active share list to client -> client selects share to join -> connected!
Technically, what you're looking for is active servers that are running your spreadsheet application.
One possibility would be for your server code to send out an "alive" message to the network every so often (say every 15 seconds). Your client code would listen for these "alive" messages, and produce a meaningful list of spreadsheet servers.
Another possibility would to to use the same database engine that you're using to store the spreadsheets to store the IP and port of the connected server code. The client code would just read the database table to get the connections.

Server UDP and port binding

I am writing this game in Java and have problems with networking architecture.
I decided I will UDP packets. I am just at the beginning, but the problem I am facing is that it seems to be that server have to respond from exactly same IP/Port to client (which is behind router which uses NAT) as client connected that server.
For example I have client A behind router. Client A has IP (local) 192.168.8.100 and it connects server B from port 1234. Server is on 11.11.11.11:2345.
When client A connects to server B it uses 192.168.8.100:1234 but router converts that to (for example) 22.22.22.22:6789.
Now, when server wants to send packets to that client it has to be from 11.11.11.11:2345.
I would like to send data from another port like 11.11.11.11:2222, but this does not seem to work, at least not with my router.
I want to use different port because I want to have two threads one for listening and one for sending data, and each thread would have it's own DatagramSocket. But, as i said once client A connects to server on port 2345, I can not send data from port 2222.
Does anyone know how is this handled? I am doing it in Java, but it's not really a language specific problem.
UPDATE
After #Perception commented I have some more questions regarding his comments:
OK, so if I understand this correctly, if I have server which is hosting 1000 games, each with 2 players, all sending/receiving will have to be done through the same DatagramSocket.
As I understand DatagramSocket is thread safe so I guess I can have one thread doing:
datagramSocket.receive();
while at the same time second thread is doing
datagramSocket.send(.....);
Correct?
Also, two threads can send data at the same time through the same DatagramSocket? Is sending in any way serialized, meaning that second send() starts only after previous send() is finished or is data being sent at the same time?
gorann, I'm not sure if I'm understanding you correctly, but it sounds like you're trying to control the port on which the server communicates with the client. There's no way to control this, and for good reasons.
This is one of the trickier differences between TCP and UDP.
When a new TCP session is initiated, the server side call to accept() gives you a new socket and the OS handles multiplexing the various sessions for you. With UDP, you need to handle the multiplexing yourself. But you need to do so in a way that works with NATs and other firewalls.
The way NAT works is that when it sees an outgoing packet, it creates a temporary rule allow packets to return along the same port pair. Data returning from a port that the client has not yet sent to will likely be blocked.
This gives you two choices:
You could do all of your communication through a single port. This is not a bad option, it just means that you need a way to identify client sessions and route them to the appropriate thread.
You could create a separate port and instruct the client to send to that one instead. Have the server listen on a fixed port. The client sends a message to there, the server then sets up a new session port and sends that number back to the client using the server's listen port. The client then sends a message to the session port, which causes the NAT to open up that port and allow return traffic. Now the client and server thread have their own private port pair.
Option 1 is a bit more work because it requires data to be exchanged between threads, but it scales up better. Option 1 is easier and more CPU efficient because each session thread can be independent, but there are a finite number of ports available.
Either way, I recommend that you have the client include a semi-unique session id in each packet so that the server has more than just the client address and port number to verify who belongs to each session.

C++/Java Sockets automatic Port allocation

I've a server (Java) and a number of clients (c++), connected by sockets.
I would like to set the ports automatically.
Assuming the IP is already known.
In the Java side I can make :
ServerSocket s = new ServerSocket(0);
So now I've a random free port on the server.
How can I know in the C++ side, what port is the server listening to?
I think is not possible, if you want establish a connection with a server, you must know in which port is the server listening, there are programs like nmap that shows you a list of opened ports in a server, but a server can have many opened ports at the same time and then, How do you know what is the port opened by your server? and in any case, is too slow and inefficient to call external tool, read and parse its output. For what reason do you need a random port service?
Other option can be get the opened socket in the server side calling to s.getLocalPort() and send it via UDP for any listening node in the network with broadcasting, and re-program the client side to listen in broadcast and when it receives a message, check if it is a port number and connect to the server using that port.
You can't, not reliably. In IP, a machine is identified by an address. A server (ie, a service) is identified by an address and a port. You clients need some form of "known service" that they can connect to.
If you, for whatever reason, absolutely want to have dynamic listening port, you could combine it with a "locator" service on a known port. For instance, have a web service/servlet on the standard http port (80). Your clients connect to the "locator" service (always on port 80) and asks which port your application is currently listening on. This is a not entirely uncommon pattern. RMI works is a similar way where you have a registry on a known port. Clients connect to the registry and asks for the location of RMI endpoints.

Categories