Java TCP Client/Server - java

I have a problem which I do not know how to proceed further in Java TCP socket issue. So far as what we can get from the Internet, it's not hard to get quite a number of working solution for TCP server & client communication in Java. However, most of the example will have their server listen to a port, and then loop until they get a client which connects to the server, then the code will perform server.accept() and move further. For example:
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(PORT);
System.out.println("Started: " + s);
try {
// Blocks until a connection occurs:
Socket socket = s.accept();
try {
System.out.println("Connection accepted: "+ socket);
It will work perfectly if there's a client connecting to the server. And, my problem is that I need to continue some other procedures even though there's no client connecting to the server. In fact, I will need to launch another JFrame to continue the procedures even if there is no client connecting to the same port and ip. However, I have been struggling but as long as there is not client connecting to the server, my Java program will hang there with white popped up JFrame.
I would need to know how to overcome this as I am not quite sure whether there's a mistake in my understanding. Please assist and advice. Thank you!
Best Regards,
Yi Ying

Sounds like you need to do work in one thread whilst waiting for network connections on another. Check out the threading tutorial. Note that since you're using Swing, you have to be careful wrt. which thread will modify your JFrame etc. and you should be aware of the SwingWorker utility.

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]

Handling Multiple TCP Connections In Java (Server-side)

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.

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();
}

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!

Should I close sockets from both ends?

I have the following problem. My client program monitor for availability of server in the local network (using Bonjour, but it does not rally mater). As soon as a server is "noticed" by the client application, the client tries to create a socket: Socket(serverIP,serverPort);.
At some point the client can loose the server (Bonjour says that server is not visible in the network anymore). So, the client decide to close the socket, because it is not valid anymore.
At some moment the server appears again. So, the client tries to create a new socket associated with this server. But! The server can refuse to create this socket since it (server) has already a socket associated with the client IP and client port. It happens because the socket was closed by the client, not by the server. Can it happen? And if it is the case, how this problem can be solved?
Well, I understand that it is unlikely that the client will try to connect to the server from the same port (client port), since client selects its ports randomly. But it still can happen (just by chance). Right?
Yes, close the socket, as soon as you detect a failure.
The socket will be "stuck" in "close_wait" if not closed properly.
Even if the socket is closed, it's state will be in time_wait for a short period.
However, if You design the application to use a different local port for each new connection, there is no need to wait for the old socket to be closed.
(As you are then creating a completly different socket, since a socket is identified by the remote-ip, remote port, local ip and local port.)
A quick/ dirty illustration of why this can't happen (note the client forcibly uses the same local port in its connection):
public class Server{
public static void main(String[] args) throws Exception {
new Thread(){
java.net.ServerSocket server = new java.net.ServerSocket(12345);
java.util.ArrayList<java.net.Socket> l = new java.util.ArrayList<java.net.Socket>();
public void run() {
try{
while(true){
java.net.Socket client = server.accept();
System.out.println("Connection Accepted: S: "+client.getLocalPort()+", C: "+client.getPort());
l.add(client);
}
}catch(Exception e){e.printStackTrace();}
}
}.start();
}
and a client (replace server address with something valid):
import java.net.InetAddress;
import java.net.Socket;
public class SocketTest {
public static void main(String[] args) throws Exception {
InetAddress server = InetAddress.getByName("192.168.0.256");
InetAddress localhost = InetAddress.getLocalHost();
Socket s = new Socket(server, 12345, localhost, 54321);
System.out.println("Client created socket");
s.close();
s = null;
System.gc();
System.gc();
Thread.sleep(1000);
s = new Socket(server, 12345, localhost, 54321);
System.out.println("Client created second socket");
s.close();
System.exit(55);
}
}
If you start the server and then try to run the client the first connection will succeed, but the second will fail with a "java.net.BindException: Address already in use: connect"
Short answer: yes, you should close socket on both ends.
Although the answer is simple, in reality it may be very hard to detect that the peer has stopped responding if you don't build some ACK/NACK scheme into your client-server protocol.
Even with your protocol ACKs your processing thread may be hanging waiting for ACKs that will never come from the client or vice versa.
If you use Blocking I/O, I would start by setting read timeouts on a socket. Unfortunately, if the peer becomes unresponsive, there is no corresponding time-out for the writes.
One blunt instrument that I found has value in our environment is to create blocking Sockets through java.nio methods and then interrupt the processing thread at configurable intervals.
Interrupting processing thread will close socket, but if you pick the timeout large enough you will know that there is a trouble. We chose this approach because application was written initially with blocking I/O and a cost to transition it to non-blocking was very high.
With the non-blocking I/O, though, you may check at a finer-grained interval the status of your connection and react more intelligently to the slow/unresponsive connections.
Though non-blocking I/O requires a higher upfront investment, I think it will pay better dividends in terms of reliability and better throughput later on.
the client operating system will not allocate the same port to a new socket so soon. there are several mechanism that prevents it. one of which is the TIME_WAIT state that reserves the port for some time after the connection is closed.
I wouldn't worry about it.
if you really need to detect disconnection you will have to implement ping/pong protocol, initiated by both the client and the server.
It sounds like your client is detecting loss of connectivity to the server (using Bonjour), but you don't have the corresponding capability in the other direction.
You're certainly going to want some kind of timeout for inactive connections on the server side as well, otherwise dead connections will hang around forever. Beyond the problem of potential IP address/port # collisions you mention, there's also the fact that the dead connections are consuming OS and application resources (such as open file descriptors)
Conversely, you might also want to consider not being too aggressive in closing a connection from the client side when Bonjour says the service is no longer visible. If you're in a wireless scenario, a transient loss of connectivity isn't that uncommon, and it's possible for a TCP connection to remain open and valid after connectivity is restored (assuming the client still has the same IP address). The optimum strategy depends on what kind of connection you're talking about. If it's a relatively stateless connection where the cost of discarding the connection and retrying is low (like HTTP), then it makes sense to toss the connection at the first sign of trouble. But if it's a long-lived connection with significant user state (like an SSH login session), it makes sense to try harder to keep the connection alive.
If you close server socket only in case of blocking socket then client socket will be closed but not vice versa.
otherwise it would be better socket in both end. Because socket is a heavy weigt for you system. It will use a local port and a remote port of your system forever.
Thanks
Sunil Kumar Sahoo

Categories