Permanent and persistent Socket connection in java - java

I've created a client-server connection, something like a chat system. Previously I was using a while loop on the client side, and it was waiting to read a message from the console every time (of course server has a while loop as well to serve forever). But now, I'm trying to first create a connection at the beginning of the session, and then occasionally send a message during the session, so to maintain a permanent and persistent connection.
Currently, without the while loop, the client closes the connection and I don't know how to find a workaround.
Here is the client code:
import java.net.*;
import java.io.*;
public class ControlClientTest {
private Socket socket = null;
// private BufferedReader console = null;
private DataOutputStream streamOut = null;
public static void main(String args[]) throws InterruptedException {
ControlClientTest client = null;
String IP="127.0.0.1";
client = new ControlClientTest(IP, 5555);
}
public ControlClientTest(String serverName, int serverPort) throws InterruptedException {
System.out.println("Establishing connection. Please wait ...");
try {
socket = new Socket(serverName, serverPort);
System.out.println("Connected: " + socket);
start();
} catch (UnknownHostException uhe) {
System.out.println("Host unknown: " + uhe.getMessage());
} catch (IOException ioe) {
System.out.println("Unexpected exception: " + ioe.getMessage());
}
String line = "";
// while (!line.equals(".bye")) {
try {
Thread.sleep(1000);
//TODO get data from input
// line = console.readLine();
line="1";
if(line.equals("1"))
line="1,123";
streamOut.writeUTF(line);
streamOut.flush();
} catch (IOException ioe) {
System.out.println("Sending error: " + ioe.getMessage());
}
// }
}
public void start() throws IOException {
// console = new BufferedReader(new InputStreamReader(System.in));
streamOut = new DataOutputStream(socket.getOutputStream());
}
}
And here is the Server code:
import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ControlServer {
private Socket socket = null;
private ServerSocket server = null;
private DataInputStream streamIn = null;
public static void main(String args[]) {
ControlServer server = null;
server = new ControlServer(5555);
}
public ControlServer(int port) {
try {
System.out
.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted: " + socket);
open();
boolean done = false;
while (!done) {
try {
String line = streamIn.readUTF();
// TODO get the data and do something
System.out.println(line);
done = line.equals(".bye");
} catch (IOException ioe) {
done = true;
}
}
close();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
public void open() throws IOException {
streamIn = new DataInputStream(new BufferedInputStream(
socket.getInputStream()));
}
public void close() throws IOException {
if (socket != null)
socket.close();
if (streamIn != null)
streamIn.close();
}
}

I would like to summarize some good practices regarding the stability of TCP/IP connections which I apply on a daily basis.
Good practice 1 : Built-in Keep-Alive
socket.setKeepAlive(true);
It automatically sends a signal after a period of inactivity and checks for a reply. The keep-alive interval is operating system dependent though, and has some shortcomings. But all by all, it could improve the stability of your connection.
Good practice 2 : SoTimeout
Whenver you perform a read (or readUTF in your case), your thread will actually block forever. In my experience this is bad practice for the following reasons: It's difficult to close your application. Just calling socket.close() is dirty.
A clean solution, is a simple read time-out (e.g. 200ms). You can do this with the setSoTimeoutmethod. When the read() method timeouts it will throw a SocketTimeoutException. (which is a subclass of IOException).
socket.setSoTimeout(timeoutInterval);
Here is an example to implement the loop. Please note the shutdown condition. Just set it to true, and your thread will die peacefully.
while (!shutdown)
{
try
{
// some method that calls your read and parses the message.
code = readData();
if (code == null) continue;
}
catch (SocketTimeoutException ste)
{
// A SocketTimeoutExc. is a simple read timeout, just ignore it.
// other IOExceptions will not be stopped here.
}
}
Good practice 3 : Tcp No-Delay
Use the following setting when you are often interfacing small commands that need to be handled quickly.
try
{
socket.setTcpNoDelay(true);
}
catch (SocketException e)
{
}
Good practice 4 : A heartbeat
Actually there are a lot of side scenario's that are not covered yet.
One of them for example are server applications that are designed to only communicate with 1 client at a time. Sometimes they accept connections and even accept messages, but never reply to them.
Another one: sometimes when you lose your connection it actually can take a long time before your OS notices this. Possibly due to the shortcomings described in good practice 3, but also in more complex network situations (e.g. using RS232-To-Ethernet converters, VMware servers, etc) this happens often.
The solution here is to create a thread that sends a message every x seconds and then waits for a reply. (e.g. every 15 seconds). For this you need to create a second thread that just sends a message every 15 seconds. Secondly, you need to expand the code of good practice 2 a little bit.
try
{
code = readData();
if (code == null) continue;
lastRead = System.currentTimeMillis();
// whenever you receive the heart beat reply, just ignore it.
if (MSG_HEARTBEAT.equals(code)) continue;
// todo: handle other messages
}
catch (SocketTimeoutException ste)
{
// in a typical situation the soTimeout is about 200ms
// the heartbeat interval is usually a couple of seconds.
// and the heartbeat timeout interval a couple of seconds more.
if ((heartbeatTimeoutInterval > 0) &&
((System.currentTimeMillis() - lastRead) > heartbeatTimeoutInterval))
{
// no reply to heartbeat received.
// end the loop and perform a reconnect.
break;
}
}
You need to decide if your client or server should send the message. That decision is not so important. But e.g. if your client sends the message, then your client will need an additional thread to send the message. Your server should send a reply when it receives the message. When your client receives the answer, it should just continue (i.e. see code above). And both parties should check: "how long has it been?" in a very similar way.

You could wrap a thread around the connection and have it periodically send a status to keep the line open, say every 30 seconds or whatever. Then, when it actually has data to send it would reset the keep alive to be 30 seconds after the last transmission. The status could be helpful to see if the client is still alive anyway, so at least it can be a useful ping.
Also, you should change your server code, you appear to only handle one connection at the moment. You should loop and when a socket connection comes in spawn a thread to handle the client request and go back to listening. I may be reading to much into what may just be your test code, though.

Make the client socket connection wrapped around a thread. Use a blocking queue to wait for messages. There should only be a single sender queue throughout your application, so use a singleton pattern.
e.g.
QueueSingleton queue = QueueSingleton.getSenderQueue();
Message message = queue.take() // blocks thread
send(message); //send message to server
When you need to send a message to the server, you can use the blocking queue to send the message.
QueueSingleton queue = QueueSingleton.getSenderQueue();
queue.put(message)
The client thread will wake up and process the message.
For maintaining the connection, use a timer task. This is special type of thread that calls a run method repetitively at specified periods. You can use this to post a message, a ping message, every so often.
For processing the received message, you could have another thread, waiting for messages on another blocking queue (receiver queue). The client thread will put the received message on this queue.

Related

Socket programming. Program creating 2 connections instead of just 1

I am building a client/server application, for some socket programming exercise.
Below is construction + run method of my server class. The server awaits a respond from the client, which in this case is just a string.
The problem is that it seems to make two connections when the client respond. From my print statements i can see that all the code in the run method is run twice, and then the first line once again.
Why would dateServer.accept(); accept a connection for only one client request?
public Server() throws Exception {
dateServer = new ServerSocket(3001);
System.out.println("Server lytter på port 3000.");
this.start();
}
public void run() {
while (true) {
try {
System.out.println("waiting for client to request");
Socket client = dateServer.accept();
System.out.println("connection established");
Connect c = new Connect(client);
clients.add(c);
this.sleep(5000);
} catch (Exception e) {
}
}
}
--EDIT--
Client code that talks to server (Message is a simple "wrapper" class"):
System.out.println("Write to server:");
String name = scanner.nextLine();
Message message = new Message(name, null);
oos.writeObject(message);
oos.flush();
If all the prints happen twice there must have been two connections. The first line prints again after that because you're in a loop.
NB:
Never ignore exceptions: especially IOExceptions.
The sleep is completely pointless. accept() will block while there are no incoming connections. You are literally wasting time here.

How to create a simultaneous connection between a server and a client on the same network in Java?

I am trying to create a MapleStory type game for my computer science final. It's basically a 2D RPG played over LAN. My question is how would I get the connection between two computers to be simultaneous?
class MagicServer extends Thread
{
private ServerSocket serverSocket;
public MagicServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
//serverSocket.setSoTimeout(10000);
}
public void run()
{
Scanner kb = new Scanner(System.in);
while(true)
{
try
{
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
System.out.println(in.readUTF());
for(int i=0; i<5; i++)
{
System.out.println(in.readUTF());
out.writeUTF(kb.nextLine());
}
server.close();
}
catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}
catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 2001;
try
{
Thread t = new MagicServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
I was experimenting with this and I can only send/recieve messages between two computers in order (i.e. server sends to client then client sends to server) and I cannot go out of order. How would I do this?
You have to de-couple your reads/writes by using multiple threads or through interlocked queues to manage your work.
In you loop, you force the serialization by doing a read then a write in the code.
There's no reason you couldn't spawn a reader thread that feeds into a queue to perform work by worker threads and writes happen on another thread. You just need to have synchronization on the work queues.
You can also poll the socket to see if there's any data available to read and if not, send any data waiting to be written.
There's more exotic ways to do it, and plenty of examples, search around and see what your comfortable with.
There's a similar thread here
You could use multiple threads to have a connection one way in one thread on one port and a connection the other way on a different port in the other thread. This could introduce some synchronization issues though, so I would recommend rethinking your design so that communication only needs to occur in one direction at a time (you can switch back and forth as often as you like if need be).

I'm having troubles with Java sockets in a client/server type application when having to accept many connections

First of all, thanks for reading. This is my first time in stackoverflow as user, although I've always read it and found useful solutions :D. By the way, sorry if I'm not clear enough explaining myself, I know that my English isn't very good.
My socket based program is having a strange behaviour, and some performance issues. The client and server communicate with each other by reading/writing serialized objects into object input and output streams, in a multi-threaded way. Let me show you the code basics. I have simplified it to be more readable and a complete exception handling for example is intentionally ommited. The server works like this:
Server:
// (...)
public void serve() {
if (serverSocket == null) {
try {
serverSocket = (SSLServerSocket) SSLServerSocketFactory
.getDefault().createServerSocket(port);
serving = true;
System.out.println("Waiting for clients...");
while (serving) {
SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
System.out.println("Client accepted.");
//LjServerThread class is below
new LjServerThread(clientSocket).start();
}
} catch (Exception e) {
// Exception handling code (...)
}
}
}
public void stop() {
serving = false;
serverSocket = null;
}
public boolean isServing() {
return serving;
}
LjServerThread class, one instance created per client:
private SSLSocket clientSocket;
private String IP;
private long startTime;
public LjServerThread(SSLSocket clientSocket) {
this.clientSocket = clientSocket;
startTime = System.currentTimeMillis();
this.IP = clientSocket.getInetAddress().getHostAddress();
}
public synchronized String getClientAddress() {
return IP;
}
#Override
public void run() {
ObjectInputStream in = null;
ObjectOutputStream out = null;
//This is my protocol handling object, and as you will see below,
//it works processing the object received and returning another as response.
LjProtocol protocol = new LjProtocol();
try {
try {
in = new ObjectInputStream(new BufferedInputStream(
clientSocket.getInputStream()));
out = new ObjectOutputStream(new BufferedOutputStream(
clientSocket.getOutputStream()));
out.flush();
} catch (Exception ex) {
// Exception handling code (...)
}
LjPacket output;
while (true) {
output = protocol.processMessage((LjPacket) in.readObject());
// When the object received is the finish mark,
// protocol.processMessage()object returns null.
if (output == null) {
break;
}
out.writeObject(output);
out.flush();
out.reset();
}
System.out.println("Client " + IP + " finished successfully.");
} catch (Exception ex) {
// Exception handling code (...)
} finally {
try {
out.close();
in.close();
clientSocket.close();
} catch (Exception ex) {
// Exception handling code (...)
} finally {
long stopTime = System.currentTimeMillis();
long runTime = stopTime - startTime;
System.out.println("Run time: " + runTime);
}
}
}
And, the client, is like this:
private SSLSocket socket;
#Override
public void run() {
LjProtocol protocol = new LjProtocol();
try {
socket = (SSLSocket) SSLSocketFactory.getDefault()
.createSocket(InetAddress.getByName("here-goes-hostIP"),
4444);
} catch (Exception ex) {
}
ObjectOutputStream out = null;
ObjectInputStream in = null;
try {
out = new ObjectOutputStream(new BufferedOutputStream(
socket.getOutputStream()));
out.flush();
in = new ObjectInputStream(new BufferedInputStream(
socket.getInputStream()));
LjPacket output;
// As the client is which starts the connection, it sends the first
//object.
out.writeObject(/* First object */);
out.flush();
while (true) {
output = protocol.processMessage((LjPacket) in.readObject());
out.writeObject(output);
out.flush();
out.reset();
}
} catch (EOFException ex) {
// If all goes OK, when server disconnects EOF should happen.
System.out.println("suceed!");
} catch (Exception ex) {
// (...)
} finally {
try {
// FIRST STRANGE BEHAVIOUR:
// I have to comment the "out.close()" line, else, Exception is
// thrown ALWAYS.
out.close();
in.close();
socket.close();
} catch (Exception ex) {
System.out.println("This shouldn't happen!");
}
}
}
}
Well, as you see, the LjServerThread class which handles accepted clients in the server side, measures the time it takes... Normally, it takes between 75 - 120 ms (where the x is the IP):
Client x finished successfully.
Run time: 82
Client x finished successfully.
Run time: 80
Client x finished successfully.
Run time: 112
Client x finished successfully.
Run time: 88
Client x finished successfully.
Run time: 90
Client x finished successfully.
Run time: 84
But suddenly, and with no predictable pattern (at least for me):
Client x finished successfully.
Run time: 15426
Sometimes reaches 25 seconds!
Ocasionally a small group of threads go a little slower but that doesn't worry me much:
Client x finished successfully.
Run time: 239
Client x finished successfully.
Run time: 243
Why is this happening? Is this perhaps because my server and my client are in the same machine, with the same IP? (To do this tests I execute the server and the client in the same machine, but they connect over internet, with my public IP).
This is how I test this, I make requests to the server like this in main():
for (int i = 0; i < 400; i++) {
try {
new LjClientThread().start();
Thread.sleep(100);
} catch (Exception ex) {
// (...)
}
}
If I do it in loop without "Thread.sleep(100)", I get some connection reset exceptions (7 or 8 connections resetted out of 400, more or less), but I think I understand why it happens: when serverSocket.accept() accepts a connection, a very small amount of time has to be spent to reach serverSocket.accept() again. During that time, the server cannot accept connections. Could it be because of that? If not, why? It would be rare 400 connections arriving to my server exactly at the same time, but it could happen. Without "Thread.sleep(100)", the timing issues are worse also.
Thanks in advance!
UPDATED:
How stupid, I tested it in localhost... and it doesn't give any problem! With and without "Thread.sleep(100)", doesn't matter, it works fine! Why! So, as I can see, my theory about why the connection reset is beeing thrown is not correct. This makes things even more strange! I hope somebody could help me... Thanks again! :)
UPDATED (2):
I have found sightly different behaviours in different operating systems. I usually develop in Linux, and the behaviour I explained was about what was happening in my Ubuntu 10.10. In Windows 7, when I pause 100ms between connections, all its fine, and all threads are lighting fast, no one takes more than 150ms or so (no slow connection issues!). This is not what is happening in Linux. However, when I remove the "Thread.sleep(100)", instead of only some of the connections getting the connection reset exception, all of them fail and throw the exception (in Linux only some of them, 6 or so out of 400 were failing).
Phew! I've just find out that not only the OS, the JVM enviroment has a little impact also! Not a big deal, but noteworthy. I was using OpenJDK in Linux, and now, with the Oracle JDK, I see that as I reduce the sleep time between connections, it starts failing earlier (with 50 ms OpenJDK works fine, no exceptions are thrown, but with Oracle's one quite a lot with 50ms sleep time, while with 100ms works fine).
The server socket has a queue that holds incoming connection attempts. A client will encounter a connection reset error if that queue is full. Without the Thread.sleep(100) statement, all of your clients are trying to connect relatively simultaneously, which results in some of them encountering the connection reset error.
Two points I think you may further consider researching. Sorry for a bit vague here but this is what I think.
1) Under-the-hood, at tcp level there are few platform dependent things control the amount of time it takes to send/receive data across a socket. The inconsistent delay could be because of the settings such as tcp_syn_retries. You may be interested to look at here http://www.frozentux.net/ipsysctl-tutorial/chunkyhtml/tcpvariables.html#AEN370
2)Your calculated execution time is not only the amount of time it took to complete the execution but includes the time until the finalization is done which is not guaranteed to happen immediately when an object is ready for finalization.

java I/O blocks thread on server side

i m working on client socket connection. client is a GPRS hardware device. i m receiving request from this client on my serversocket and then opening multiple threads. my problem is that when device/client close the socket then my IO detects that throws an exception but when i put off the battery from the device while sending the request to the serversocket it is blocked without throwing any exception. somebody suggested me to use setSOTimeout() to comeout from the blocking thread.
i have tried Socket.setSOTimeout(int) . but this is not working out in my case. i m sending my code properly.
// inside main class---
public class ServerSocketClass{
public ServerSocketClass() {
try{
serverSocket = new ServerSocket(port);//creating a serversokcet on a port
System.out.println("Server waiting for client on port " +
serverSocket.getLocalPort());
} catch (Exception e) {
e.printStackTrace();
handleExceptions("errorServerSocketOpen.txt", e);
System.exit(0);
}
try {
while (true) {
Socket clientSocket = serverSocket.accept();//accepting the client connection and //creating client socket
new AcceptConnection(clientSocket);//calling the constructor of other //class to open a new thread
System.out.println("constructor called.....");
}
} catch (Exception e) {
handleExceptions("errorClientSocketOpen.txt", e);
}
}
}
//inside other class---
public class AcceptConnection implements Runnable {
public AcceptConnection(Socket socket) {
this.clientSocket = socket;
if (clientSocket != null) {
new Thread(this).start();
}
public void run() {
// clientSocket.setSoTimeout(60000);// this is what i added.timeout on each client socket opened in threads
InputStream inputStream = clientSocket.getInputStream();
DataOutputStream dataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
byte[] mainBuffer = new byte[2048];
int len = -1, totalLength = 0;
debugInfo = " GOING TO READ FROM SOCKET.... " + "\n";
while ((len = inputStream.read(mainBuffer)) > -1) {
totalLength = len;
}//end of while
} }//end of other class
now my problem is that when multiple threads are opened and i send the data from client than after 60 seconds it closes the main socket and stops receiving the data.and a readtimeout error occurs.
please help me out and tell me how my objective could be fulfilled.
thanks in advance
**
#stephen
**
ok stephen got it what u r trying to say... u r right on your statement "Well yes ... that's what you told it to do."May be i m not able to make u understand my problem or i m not getting the setSoTimeout() logic as i m newbie in java.
i would like to ask one more time...
this is how i m creating a new client socket for each client connection and opening a new thread for each client connection.
while (true) {
Socket clientSocket = serverSocket.accept();//accepting the client connection and //creating client socket
new AcceptConnection(clientSocket);//calling the constructor of other class to open a new thread
System.out.println("constructor called.....");
}
public void run() {
// clientSocket.setSoTimeout(60000);// this is what i added.timeout on each uclient socket opened in threads
........................................
.......................................
}
now i want to say if i m opening a new thread for a new client connection and i m separately putting setSoTimeout() on each client connection object then if a particular thread A is blocked on I/O while reading then after a timeout set in setSoTimeout(50000) ,say 50 sec ,only thread A should come out of read and give the exception, not other threads running simultaneously say B,C,D.but in my case after a timeout all threads returns after giving exception and in fact any new client connection gives the same error and server application stops receiving any data on read.
i want only thread A should give exception and come out from read without affecting other client socket objects(or threads).
now i hope i have told u everything about my confusion and problem.
please help me out and thanks a lot.
now my problem is that when multiple threads are opened and i send the data from client than after 60 seconds it closes the main socket and stops receiving the data.and a readtimeout error occurs.
Well yes ... that's what you told it to do.
As I think I said in my answer to your previous question, you cannot distinguish between these cases:
The client has no data to send for a period.
The network is partitioned for a period.
The client has disappeared from the network.
Another option that you have is to call Socket.setKeepAlive() to enable TCP keepalives. This causes the a special "keepalive" handshake to be performed periodically to ensure that the TCP/IP connection is still alive. Unfortunately, it doesn't look like you can set the TCP/IP keepalive interval in Java.
EDIT
NIO won't help. When I said "cannot" above ... I meant that it is PHYSICALLY IMPOSSIBLE to do it. Here's an analogy to help you understand.
The only communication between Outer
WoopWoop and the rest of the world is
by letter. Once a week my friend in
Outer WoopWoop (who lives alone) posts
a letter to me to fill me in on the
gossip. Last week I didn't receive a
letter from my friend. How can I tell if:
my friend has died,
my friend had no gossip last week,
the Outer WoopWoop postal workers have been on strike, or
all of the above?
The correct answer is that I cannot tell.

Checking if a ClientSocket has disconnected in java hangs

This is a follow up to:
this question
Basically, I have a server loop that manages a connection to one solitary client. At one point in the loop, if a ClientSocket exists it attempts a read to check if the client is still connected:
if (bufferedReader.read() == -1) {
logger.info("CONNECTION TERMINATED!");
clientSocket.close();
setUpSocket(); // sets up the server to reconnect to the client
} else {
sendHeartBeat(); // Send a heartbeat to the client
}
The problem is, that once a socket has been created the application will hang on the read, I assume waiting for data that will never come, since the client never sends to the server. Before this was OK, because this correctly handled disconnects (the read would eventually fail when the client disconnected) and the loop would attempt reestablish the connection. However, I now have added the above sendHeartBeat() method, which periodically lets the client know the server is still up. If the read is holding the thread then the heartbeats never happen!
So, I assume I am testing if the connection is still up incorrectly. I could, as a quick hack, run the bufferedReader.read() in a seperate thread, but then I'll have all sorts of concurrency issues that I really don't want to deal with.
So the question is a few fold:
Am I checking for a client disconnect correctly?
If not, how should I do it?
If I am doing it correctly how I do I get the read to not hold the process hostage? Or is threading the only way?
When you create your socket, first set a timeout:
private int timeout = 10000;
private int maxTimeout = 25000;
clientSocket.setSoTimeout(timeout);
With this, if a read times out you'll get java.net.SocketTimeoutException (which you have to catch). Thus, you could do something like this, assuming you've previously set the SO_TIMEOUT as shown above, and assuming that the heartbeat will always get a response from the remote system:
volatile long lastReadTime;
try {
bufferedReader.read();
lastReadTime = System.currentTimeMillis();
} catch (SocketTimeoutException e) {
if (!isConnectionAlive()) {
logger.info("CONNECTION TERMINATED!");
clientSocket.close();
setUpSocket(); //sets up the server to reconnect to the client
} else {
sendHeartBeat(); //Send a heartbeat to the client
}
}
public boolean isConnectionAlive() {
return System.currentTimeMillis() - lastReadTime < maxTimeout;
}
A common way of handling this is setting the timeout to some number (say 10 seconds) and then keeping track of the last time you successfully read from the socket. If 2.5 times your timeout have elapsed, then give up on the client and close the socket (thus sending a FIN packet to the other side, just in case).
If the heartbeat will not get any response from the remote system, but is just a way of ultimately generating an IOException earlier when the connection has fallen down, then you could do this (assuming that the sendHeartBeat itself will not throw an IOException):
try {
if (bufferedReader.read() == -1) {
logger.info("CONNECTION TERMINATED with EOF!");
resetConnection();
}
} catch (SocketTimeoutException e) {
// This just means our read timed out ... the socket is still good
sendHeartBeat(); //Send a heartbeat to the client
} catch (IOException e) {
logger.info("CONNECTION TERMINATED with Exception " + e.getMessage());
resetConnection();
}
....
private void resetConnection() {
clientSocket.close();
setUpSocket(); //sets up the server to reconnect to the client
}
You are checking correctly, you can should add a try catch with IOException in case it occurs.
There is a way to avoid threading, you can use a Selector with a non-bloking socket.
public void initialize(){
//create selector
Selector selector = Selector.open();
ServerSocketChannel acceptSocket = ServerSocketChannel.open();
acceptSocket.configureBlocking(false);
String bindIp = "127.0.0.1";
int bindPort = 80;
acceptSocket.socket().bind(new InetSocketAddress(bindIp, bindPort));
//register socket in selector for ACCEPT operation
acceptSocket.register(selector, SelectionKey.OP_ACCEPT);
this.selector = selector;
this.serverSocketChannel = serverSocketChannel;
}
public void serverStuff() {
selector.select(maxMillisecondsToWait);
Set<SelectionKey> selectedKeys = selector.selectedKeys();
if( selectedKeys.size() > 0 )
{
if( key.isAcceptable() ){
//you can accept a new connection
SocketChannel clientSk = serverSocketChannel.accept();
clientSk.configureBlocking(false);
//register your SocketChannel in the selector for READ operations
clientSk.register(selector, SelectionKey.OP_READ);
} else if( key.isReadable() ){
//you can read from your socket.
//it will return you -1 if the connection has been closed
}
}
if( shouldSendHeartBeat() ){
SendHeartBeat
}
}
You should add error checking in your disconnection detection. Sometimes an IOException may be thrown when the connection to the other end is lost.
I am afraid that threading is unavoidable here. If you don't want to block the execution of your code, you need to create a separate thread.

Categories

Resources