Handling Multiple TCP Connections In Java (Server-side) - java

I'm in the process of writing a messaging program, and I'm running into a spot where I'm having trouble understanding how to pass a socket over to a new thread for handling outbound messages via TCP. I'm currently using UDP packets for messages coming from a client, to the server, which, being UDP, doesn't require very much processing, as it's simply listening for incoming packets, before it de-serializes the objects, and processes them as needed in a separate thread. My problem now is, I'm setting up a client initiated TCP socket for reverse traffic, from the server to the assorted clients that connect. I've done a bit of research, and I already understood that each client should have their own thread for handling outgoing messages, along with another thread simply for accepting the incoming connections. I'm unsure of how to actually achieve this, and I've done some research into the topic.
I've found this: http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html
The resource above basically verified my original suspicion that this would have to be handled by threads dedicated to the client. They included psuedo code here, which is representing my listener thread.
while (true) {
accept a connection;
create a thread to deal with the client;
}
I'm a bit of a visual learner, and I have been searching for some type of an example where this is done. I'm unsure of what variable I'd be passing over to the thread that keeps the original connection open, and pushes data back to clients. I'm also having a little bit of trouble grasping whether it even keeps the same socket open, or if a new one needs to be established, which then, makes me believe a firewall could interfere, but I know that won't be the case.
Can somebody explain this for me in detail? If possible, an example would be greatly appreciated!
I'll be likely replying and commenting on responses in about 15-30 minutes from the time this is posted.

What you are doing sounds correct. I typically implement a server like this (simplified version with no tracking of the clients and so on):
#Override
public void run() {
//start listening on the port
try {
serverSocket = new ServerSocket(port);
logger.info("Listening for connections on port " + port);
} catch (IOException e) {
logger.error("Cannot start SocketListener on port " + port + ". Stopping.", e);
return;
}
while (!stopped) {
try {
//wait for connection
Socket newSocket = serverSocket.accept();
ClientThread client = new ClientThread(newSocket);
Thread clientThread = new Thread(client, MEANINGFUL_THREAD_ID);
clientThread.start();
} catch ...
}
}
where serverSocket is a ServerSocket instance variable and stopped is a flag I use to stop the listener thread.
So to answer your questions in the comment, you normally pass the Socket object to each client thread so that that thread can work with the input and output stream and handle closing of the socket and so on. Once you "accept" a socket connection, you do not need to recreate the ServerSocket, you simply call .accept() again to start waiting for a new connection.
In most cases, you will need to keep track of all client threads in your server so that you can stop the server gracefully or do broadcasts for example.

Related

Java listening on multiple server ports for client attempt to connect

OK. I feel dumb. I cannot find what I'm looking for.
I am opening 50 ServerSockets and adding them to a List of ServerSockets:
ServerSocket ss = new ServerSocket(getPortNumber());
SOCKETS.add(ss);
I get that I need a new thread for each connection:
new Thread() {
public void run() {
ServerSocket ss = new ServerSocket(getPortNumber());
while(true) {
Socket client = ss.accept();
//handle client
}
}.start();
So, my question is, "Do I have to use a while loop until I get a connection?"
I mean, is there a way to listen for an attempt to connect before using the ss.accept to assign Socket client?
Do I have to use a while loop until I get a connection?
It depends. If you're only expecting one connection you don't need a while loop: otherwise, you do.
I mean, is there a way to listen for an attempt to connect before using the ss.accept to assign Socket client?
The question doesn't make sense. That's what accept() does.
NB creating the ServerSocket already puts the port into listening state that can be connected to. But it is accept() that accepts connections, and nothing else.
The fact that you're creating 50 listening ports already indicates a severe design problem. You only need one. Don't waste system resources.
This all sounds like an XY problem.
We decided that (in our case) it is best to have a dedicated server socket for each client. Therefore, I am following the answer to this SO question:
Server Listening on Multiple Ports [Java]

Java TCP server socket accepting multiple clients on different ports

I am trying to build a socket that is capable of having multiple TCP connections, at different ports with multiple clients simultaneously.
The situation is my socket has to receive commands from a server and redirect the commands to wireless sensors (one command to one sensor, not broadcasting), and be able to collect the corresponding data from the sensors and then send them back to the server. Connections with the server would be using TCP, but connections with the sensors could be TCP or UDP.
My main concern are the TCP connections. I am looking into java multithreaded or thread pooled socket tutorials. But the examples I’ve seen were only using a single port to handle all the connections. I’m also trying to look into other possible solutions: utilizing tomcat server, java servlet/JSP, socket channel etc…
I’m not an expert in networking or socket programming so I really hope someone with experience could point me in the right direction. Thank you for any help you can provide in this situation.
Not sure if I fully understand but it seems like it is unnecessary for me to obtain multiple ports for my situation. Seems like I would need to focus on multi threaded sockets and Java NIO topics?
And again thank you for the advice and help.
This is rather a big project to be answered in full here. But here are some general guides:
1) If you want to create a socket on one port you need to create one thread to run it. That is called a server socket. Therefore, from the main thread u need to call one thread for every socket on every port.
2) Each server socket keeps listening on a certain port and waits for clients to connect.
when a client actually connects, the server socket should open another thread for that connection alone and return back to listening.
while(myServerSocket.accept())
{
Open connection thread
}
My advice would be to learn online about how to open threads from classes and then follow the guide above.
Unless you are going over 10k connections then most web servers would be able to handle the traffic.
But maybe you should get more details on the difference between a connection, a socket, and a port. Take a look at this: What is the difference between a port and a socket?
On your question: one port can handle many connections. You don't need different ports for different connections.
My understanding of this request is that you would need to deploy several instances of your server socket application listening on their respective ports and capable of servicing multiple client connections.
By way of mathematical induction, if you have written your server app properly it should work anywhere it is deployed. Below is sample of what your server socket application run should look like
public void run()
{
try
{
while(true)
{
try
{
Thread client_thread= new Thread(new ClientReqProcessor(serverSocket.accept()));
client_thread.start();
}
catch(Exception ex)
{
logger.error("connection error: "+ex.getMessage());
}
}
}
}
Why do you want to use multiple ports? You can have multiple connections on one listening port. The connection itself runs always on different ports.
while (running)
{
try
{
#SuppressWarnings("resource")
Socket socket = serverSocket.accept();
new ServerHandler(socket); // ServerHandler is your class to handle one connection.
}
catch (IOException e)
{
...
}
}
When you really need different ports, you can create a lot of Threads, each with a ServerSocket. Ports are one of the most limited resources on your computer. The running Threads are much cheaper.
for(int i = 1000; i < 1100; i++)
{
final int port = i;
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
new ServerHandler(socket); // ServerHandler is your class to handle one connection.
}
catch(IOException e)
{
...
}
}
}).start();
}

Checking for incoming connections to ServerSocket

Is there a way to check for incoming connections to ServerSocket, so my server would not stop when waiting for someone to connect.
I need something like
try {
if (server.thereisarequest()) {
Socket socket = server.accept();
}
}
Are you sure you want this? Having the code presented, only one thread is waiting. Run another threads which handle accepted connections so that your server doesn't stop.
You can also use java non-blocking asynchronous I/O (nio and nio2), but in the background there is a thread on duty anyway.
Keep it simple... use an infinite while loop to make server look for the incoming request... thats how most of the servers works..
while (true) {
incoming = s.accept(); // incoming is of type Socket.
}
You can create a new thread to accept connections.
Then you have 2 choices:
Process the socket in a new thread
Put the sockets in a queue (ConcurrentLinkedQueue) and check it queue from you main thread.

Expanding my Java program to send a alert message to other computers

I've written a java intake program that send an PDF-formatted intake to a shared folder so that other people in the network can read it. However, there is not a way for the other people to know that an intake was sent unless someone tells them, so I want the program to send an alert message to the other computers telling them that an intake has been sent.
Now I've done some research into this and figured that TCP is the way to go since it's reliable. I also know that this is a one-to-many sending going on, so I assume that my Intake program will act as the server an the other computers will be the client, or should it be the other way around?
Now I assume that I have to create a client program that listens to the server and waits for it to send a message.
With that in mind, how do I:
Create a client program that listens for the message continuously until the program is closed. I assume that I'll be using "while (true)" and sleep. If so, how long do I put the program to sleep?
Make it as part of Windows service so that can load up when Windows start.
On the server end, how do I:
Send messages to more than one computer, since TCP is not capable of multicasting or broadcasting. I assume an array/vector will play a part here.
Oh, this is a one-way communication. The client doesn't have to respond back to the server.
First of all, UDP is quite reliable (in fact, as reliable as the IP protocol itself). TCP simply ensures that the data was received which involved quite a lot of magic in the back end. Unless you absolutely need to be sure that other machines got the message, you could do it with UDP. Mind that I'm not saying “Don't use TCP”, I just want to make it straight that you should take UDP into consideration as well.
Anyway, yes, you can create a simple listening program. Here is an example of a client in Java that reads messages from the server. It overrides the run method of a Thread class:
public void run() {
try {
String messageFromServer = reader.readLine();
while (messageFromServer != null) {
// Do things with messageFromServer here
// processor.processFromServer(messageFromServer);
messageFromServer = reader.readLine(); // Blocks the loop, waits for message
}
}
catch (IOException e) {
// Handle your exception
}
}
Amongst other things, my thread was set up as such:
public CommunicationThread(String hostname, int port, int timeout) throws IOException, SocketTimeoutException {
InetSocketAddress address = new InetSocketAddress(hostname, port);
socket = new Socket();
socket.connect(address, 2000); // 2000ms time out
// You can use the writer to write messages back out to the server
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
Now, regards to server-side you can do something as follows:
Write a program to allow clients to contact, given that they know your address.
Accept the connections, and store the sockets in a list.
When you need to send out a message, traverse the list and send the data to everyone on it.
You can start listening on your server with
this.socket = new ServerSocket(port);
You could (or even should(?)) make it threaded so that you can accept clients while serving others. You can accept new clients with:
socket.accept(); // Blocks, waiting for someone to connect, returns open socket
Feel free to pass that to a whole new class which can deal with BufferedWriter (and maybe even BufferedReader if you want to read from clients as well). That class is where you would implement things such as writeToClient(message)
Consider the situation where you have a ClientConnection class that has writeToClient(String s) method and (Server server, Socket socket) and initialized ArrayList conList.
Here is how you would follow:
In a separate thread in Server, accept connections with
ClientConnection con = new ClientConnection(this, socket.accept());
conList.add(con);
Then, when you want to write to clients:
for (ClientConnection c : conList) {
c.writeToClient("I'm sending you a message!");
}
I hope you get a vague idea of what you need to do. Read the Socket documentation, it's very useful. Also, as always with threaded applications, make sure you aren't doing things such as modifying a list while traversing it and avoid race conditions.
Good luck!

How to make an accepted socket non-blocking in java

I'm accepting a connection from a client and then passing that connected socket off to another object, however, that socket needs to be non-blocking. I'm trying to use getChannel().configureBlocking(false) but that does not seem to be working. It needs to be non-blocking because this the method below is called every 100ms. Is there some other way that I should be making this non-blocking? Thanks for any help!
public void checkForClients() {
DataOutputStream out;
DataInputStream in;
Socket connection;
InetAddress tempIP;
String IP;
try {
connection = serverSocket.accept();
connection.getChannel().configureBlocking(false);
System.err.println("after connection made");
in = new DataInputStream(connection.getInputStream());
out = new DataOutputStream(connection.getOutputStream());
tempIP = connection.getInetAddress();
IP = tempIP.toString();
System.err.println("after ip string");
// create a new user ex nihilo
connectedUsers.add(new ConnectedUser(IP, null, connection, in, out));
System.err.println("after add user");
} catch (SocketTimeoutException e) {
System.err.println("accept timeout - continuing execution");
} catch (IOException e) {
System.err.println("socket accept failed");
}
}
Two things:
Why aren't you using a ServerSocket if you're listening for connections?
If you want to accept multiple clients you want to use a loop.
The basic structure of a multi-client server is:
while (true) {
// accept connections
// spawn thread to deal with that connection
}
If the issue is blocking on the accept() call, well that's what accept() does: it blocks waiting for a connection. If that's an issue I suggest you have a separate thread to accept connections.
See Writing the Server Side of a Socket.
I would expect your code to block on the accept call, never getting to the configureBlocking call.
I typically spin off a separate thread for each socket connection, and let it block until a connection is actually made/accepted This allows the main thread to continue unblocked while it is waiting for client connections.
If you're looking for non-blocking sokets, my suggestion is to use Selectors and ServerSocketChannels with the NIO package.
http://java.sun.com/j2se/1.4.2/docs/guide/nio/
If the typical blocking socket doesn't give you the availability you need (a connection every 100ms does seem tight). You should look at a non-blocking socket. Here is a tutorial. You can also look at Apache MINA to make this easier.
One approach is to use an I/O loop (event loop) in a single threaded environment. Take a look at Deft web server for inspiration. (Especially the start() method in IOLoop)

Categories