Ok so my question is really simple as I have it I pretty much have a server and a client program, however I don't want my server to have to be on for client to run, so I want to have it so the client never stops searching for server and all I have to do is turn server on, does anyone know how I'd do that? thanks
Put it in a while loop. Keep in mind that this will stall your program until it connects, so you should probably do this on a separate thread.
boolean done = false;
while (!done) {
try {
// Socket initialization code
} catch (IOException e) {
if (!e.getMessage().equals(/* Error code for unable to find server */) {
done = true;
}
}
Related
I'm using this code to detect if a server isn't connect
private boolean isServerListening() {
try {
s = new Socket("localhost", PORT);
return true;
} catch (IOException e) {
System.out.println(e);
return false;
}
}
and Thread to handle suddenly disconnected server
Thread checkServer = new Thread(() -> {
while (true) {
if (isServerListening()==false) {
JOptionPane.showMessageDialog(null, "Server is disconnected!");
System.exit(0);
}
}
});
The problem is:
I think the method took too much time (about 4 seconds) to execute and return.So is there a proper way?
No matter the server is connected or not, this Thread still show the JOptionPane and terminate my program.Am I wrong at some point?
There is no general solution that fits all. Bsically there are different types of "lost connection":
Your computer disconnects, so it knows immediatley that the connection is closed.
The other side disconnects, it might happen that this signal does not reach your computer, so it will still think that you are connected.
The physical connection breaks, both sides cannot inform the other side.
The Socket has the methods isConnected() and isClosed() which you should use.
The only way to check a connection surely is by sending a message and receiving an answer. Then it might take up to 60 seconds (by default) until your computer notices the lost connection.
Explanation
I'm revisiting the project I used to teach myself Java.
In this project I want to be able to stop the server from accepting new clients and then perform a few 'cleanup' operations before exiting the JVM.
In that project I used the following style for a client accept/handle loop:
//Exit loop by changing running to false and waiting up to 2 seconds
ServerSocket serverSocket = new ServerSocket(123);
serverSocket.setSoTimeout(2000);
Socket client;
while (running){ // 'running' is a private static boolean
try{
client = serverSocket.accept();
createComms(client); //Handles Connection in New Thread
} catch (IOException ex){
//Do Nothing
}
}
In this approach a SocketTimeoutException will be thrown every 2 seconds, if there are no clients connecting, and I don't like relying on exceptions for normal operation unless it's necessary.
I've been experimenting with the following style to try and minimise relying on Exceptions for normal operation:
//Exit loop by calling serverSocket.close()
ServerSocket serverSocket = new ServerSocket(123);
Socket client;
try{
while ((client = serverSocket.accept()) != null){
createComms(client); //Handles Connection in New Thread
}
} catch (IOException ex){
//Do Nothing
}
In this case my intention is that an Exception will only be thrown when I call serverSocket.close() or if something goes wrong.
Question
Is there any significant difference in the two approaches, or are they both viable solutions?
I'm totally self-taught so I have no idea if I've re-invented the wheel for no reason or if I've come up something good.
I've been lurking on SO for a while, this is the first time I've not been able to find what I need already.
Please feel free to suggest completely different approaches =3
The problem with second approach is that the server will die if an exception occurs in the while loop.
The first approach is better, though you might want to add logging exceptions using Log4j.
while (running){
try{
client = serverSocket.accept();
createComms(client);
} catch (IOException ex){
// Log errors
LOG.warn(ex,ex);
}
}
Non-blocking IO is what you're looking for. Instead of blocking until a SocketChannel (non-blocking alternative to Socket) is returned, it'll return null if there is currently no connection to accept.
This will allow you to remove the timeout, since nothing will be blocking.
You could also register a Selector, which informs you when there is a connection to accept or when there is data to read. I have a small example of that here, as well as a non-blocking ServerSocket that doesnt use a selector
EDIT: In case something goes wrong with my link, here is the example of non-blocking IO, without a selector, accepting a connection:
class Server {
public static void main(String[] args) throws Exception {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
while(true) {
SocketChannel sc = ssc.accept();
if(sc != null) {
//handle channel
}
}
}
}
The second approach is better (for the reasons you mentioned: relying on exceptions in normal program flow is not a good practise) allthough your code suggests that serverSocket.accept() can return null, which it can not. The method can throw all kinds of exceptions though (see the api-docs). You might want to catch those exceptions: a server should not go down without a very good reason.
I have been using the second approach with good success, but added some more code to make it more stable/reliable: see my take on it here (unit tests here). One of the 'cleanup' tasks to consider is to give some time to the threads that are handling the client communications so that these threads can finish or properly inform the client the connection will be closed. This prevents situations where the client is not sure if the server completed an important task before the connection was suddenly lost/closed.
I am writing an application that streams data that clients can then listen to and receive. However I am running into an issue with closing a socket when a client is no longer listening.
What I do is create a ServerSocket, when then waits for a connection and once it is connected, I start streaming the data. However, once the client is no longer connected, I am stuck in a loop of streaming and cannot tell if anyone is listening. Is there a way around this?
try {
serverSocket = new ServerSocket(STREAM_PORT);
Socket clientSocket = serverSocket.accept();
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream(), true);
while (true) {
pw.println("some data");
}
} catch (SocketException e) {
// Never occurs when client disconnects
} catch (IOException e) {
// Never occurs when client disconnects
}
I have tried using socket.isClosed(), but it always returns false. Am I approaching this from the wrong angle, or is there a way to do it. I would ideally not want the client to have to send the server a "end" command.
EDIT: Edited to reflect what current code I am running after #Rod_Algonquin suggestion
As you are using PrintWriter, which swallows I/O exceptions, you need to call checkError() after each write to see if an error has occurred.
I was unsure whether this issue is to do with the network, but I'm trying to get a simple server to send messages to multiple clients. It works fine when testing on my own computer, but over the network to a different computer has issues.
The client connects to the server fine, the first message sent to the client SHOULD be 'Server : Hello, World!', but a blank string comes through. Then the second string is always read as it should be, and all the rest usually come out as blank strings. The server sends info via a PrintStream, using autoflush.
Below is the part of the Client program which reads input. I believe if anything, there is an issue here, but I'm not sure what since I'm a little new to sockets and networking things. The server sends a line of text each 500 milliseconds, counting up to each client. I've tried changing this number to something higher but the client still doesn't receive the correct messages. The client should receive the messages and print them to the screen, replying with the replies seen below at 5,10,15 and 20.
try {
socket.setSoTimeout(10);
String line;
while((line = input.readLine())!=null){
if (!line.equals("")){
// Replies
if (output != null) {
if (line.endsWith(" 20")){
output.println("Reached 20!");
}else if (line.endsWith(" 15")){
output.println("Reached 15!");
}else if (line.endsWith(" 10")){
output.println("Reached 10!");
}else if (line.endsWith(" 5")){
output.println("Reached 5!");
}
}
messages.add(line);
if (messages.size() >= 8){
messages.remove(0);
}
}else{
messages.add("EMPTY STRING!!");
if (messages.size() >= 8){
messages.remove(0);
}
}
}
} catch (SocketTimeoutException e){
// Timed out
} catch (Exception e) {
System.err.println("Connection lost");
break;
}
(Quick Edit: Should probably mention this is in a while loop inside the run method since I implemented Runnable on my class.)
When using input.readLine(), should I be checking something before to make sure it doesn't come out as just empty strings? Is it because of the timeout I have put on it?
Thanks in advance, and I should also mention I'm new to stackoverflow, If I'm doing anything wrong please say! :)
Okay, Well. Turns out it was to do with the timeout being too small. I put it up to a whole second and now it prints out fine. Thanks anyway people :)
I have implemented a socket with a server and single client. The way it's structured currently, the server closes whenever the client closes. My intent is have the server run until manual shutdown instead.
Here's the server:
public static void main(String args[])
{
;
try
{
ServerSocket socket= new ServerSocket(17);
System.out.println("connect...");
Socket s = socket.accept();
System.out.println("Client Connected.");
while (true)
{
work with server
}
}
catch (IOException e)
{
e.getStackTrace();
}
}
I've tried surrounding the entire try/catch loop with another while(true) loop, but it does nothing, the same issue persists. Any ideas on how to keep the server running?
It looks like what's going to happen in your code there is that you connect to a client, infinitely loop over interactions with the client, then when someone disrupts the connections (closes clearning, or interrupts it rudly - e.g., unplug the network cable) you're going to get an IOException, sending you down to the catch clause which runs and then continues after that (and I'm guessing "after that" is the end of your main()?)...
So what you need to do is, from that point, loop back to the accept() call so that you can accept another, new client connection. For example, here's some pseudocode:
create server socket
while (1) {
try {
accept client connection
set up your I/O streams
while (1) {
interact with client until connection closes
}
} catch (...) {
handle errors
}
} // loop back to the accept call here
Also, notice how the try-catch block in this case is situated so that errors will be caught and handled within the accept-loop. That way an error on a single client connection will send you back to accept() instead of terminating the server.
Keep a single server socket outside of the loop -- the loop needs to start before accept(). Just put the ServerSocket creation into a separate try/catch block. Otherwise, you'll open a new socket that will try to listen on the same port, but only a single connection has been closed, not the serverSocket. A server socket can accept multiple client connections.
When that works, you probably want to start a new Thread on accept() to support multiple clients. Simplest way to do so is usually to add a "ClinentHandler" class that implements the Runnable interface. And in the client you probably want to put reading from the socket into a separate thread, too.
Is this homework / some kind of assignment?