Thread sleep in connection - java

I have a network client which tries 3 times in a loop to connect to server. During this time I use sleep thread. Is there any way to replace Thread.sleep(700); with some code which skip the waiting period right after the client is connected.
NClient pc;
if (pc == null)
{
try
{
Thread.sleep(700);
}
catch (InterruptedException x)
{
//TODO
}
if (pc != null)
{
outPrint.println("Connected");
break;
}
}
I would like to improve the user experience by reducing the waiting period in which the connection negotiation is in progress. What are the options in Java to do this?

The answer to this question depends on the implementation of NClient. Typically, I'd use a connect timeout for this. The example below indicates how to do this with a Socket. I don't know what NClient is, so I can't give you an NClient example unfortunately.
Create a method that attempts to connect - up to 3 times
Socket connectToServer() {
Socket socket = new Socket();
final int connectTimeoutMs = 700;
for (int i=0; i<3; i++) {
try {
// the call to connect blocks the current thread for a maximum of 700ms if it can't connect
socket.connect(new InetSocketAddress("localhost", 8080), connectTimeoutMs);
} catch (IOException e) {
// failed to successfully connect within 700 milliseconds
e.printStackTrace();
}
}
return socket;
}
Use the above as follows
Socket socket = connectToServer();
if (socket.isConnected()) {
// do stuff with the valid socket!
}
In short, use a connect timeout!

Related

How to keep Java Client Socket alive when network connection drops?

I often have to restart my client application when my internet connection goes down for a few seconds. Do I have to create new connection on every disconnect or is there a way to keep client socket alive while "waiting?" for connection to be reestablished? I am not sure when exactly the disconnect happens. Is it when we try to write back to the outputstream as readLine() might be able to survive the disconnect? Or is the "&& !kkSocket.isClosed()" check redundant and closes the while loop? Thanks in advance.
try {
kkSocket = new Socket("12.345.67.899", 1234);
out = new PrintWriter(kkSocket.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
return;
}
try (
BufferedReader in = new BufferedReader(
new InputStreamReader(kkSocket.getInputStream()));
) {
String fromServer;
while ((fromServer = in.readLine()) != null && !kkSocket.isClosed()) {
doSomething(fromServer);
out.println("Back to server");
}
} catch (IOException e) {
Thread.currentThread().interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
It is not possible to make a client socket "wait" for the connection to be reestablished. What you can do instead is creating a loop that will retry to connect to the server upon disconnect, for example based on a timer (every X seconds). This way you avoid having to manually restart your application.
Note that you would have to implement some way of exiting this retry loop to exit your program. (ex: throw a keyboard event, exit after X consecutive unsuccessful attempts etc...)

Stop Socket Thread for specific IP Address in Java Multithreading

I'm setting up a server software to accept multiple connection from ESP32 board. During testing, the server able to receive multiple connections and multiple message in 100ms without stuck. However, the problem now is the server cannot detect an offline disconnect from the ESP32. I need to stop specific thread for the stop connection because when the board is disconnected, it will try to reconnect again. A new thread is open for the new connection but the old thread is still running.
The connected clients will be listed in a JTable in Server side. I have tried to use Thread.interrup() but it's not working because the code is made to waiting receive something from client to start connection.
Below is the code to remove same IP Address to avoid redundant connection because I'm using fix IP Address and also the interrupt thread.
How do I stop the running thread of remove IP Address because of disconnection?? To get successful interrupt thread do I need to stop readLine() in run()? Below is a code snippet in ClientHandler and the run() where it will wait for data/message from client to connect.
socket = clientSocket;
//Get client IP Address
clientIP = socket.getInetAddress().getHostAddress();
Socket socket1;
for(int i = 0; i < clientSockets.size(); i++) {
socket1 = clientSockets.get(i);
if(socket1.getInetAddress().getHostAddress().equals(clientIP)) {
tableModel.removeRow(i);
clientSockets.remove(socket1);
JTextArea.append(clientIP + " - Disconnected.");
JTextArea.append("1. Before interrupt--------");
for(Thread t : Thread.getAllStackTraces().keySet())
{
JTextArea.append(t.getName());
}
JTextArea.append("--------");
for(Thread t : Thread.getAllStackTraces().keySet())
{
if(t.getId() == threads.get(i).getId())
{
threads.remove(i);
t.interrupt();
break;
}
}
JTextArea.append("2. After interrupt--------");
for(Thread t : Thread.getAllStackTraces().keySet())
{
JTextArea.append(t.getName());
}
JTextArea.append("--------");
}
}
run(){
while ((message = netin.readLine())!=null)// Need to stop the readLine() here to interrupt the thread if not cannot stop it.
try {
String[] data = message.split("&");
Vector<Object> tableRow = new Vector<Object>();
if(data[0].equals("connection")) {
msg1= data[1];
msg2= data[2];
msg3= data[3];
tableRow.add(clientIPAddress);
tableRow.add(msg1);
tableRow.add(msg2);
tableRow.add(msg3);
// Add a client row into the table
tableModel.addRow(tableRow);
}
JTextArea.append("Stop Thread.");
} catch (Exception ex) {
JTextArea.append("Run Exception:" + Thread.currentThread().getId() + "-" + ex);
}

Socket server stream messages in stream are mixed

I am implementing multiplayer game with server socket mechanism.
Game is running in one loop mechanism.
Server only broadcast any message to every player connected.
Server creates thread for every connected player
Messages are JSONs and they are being sent every 100ms from client side.
Messages are being broadcasted by server and read by client without any interval.
This is server loop:
while (true) {
try {
System.out.println("LISTENING...");
Socket clientSocket = serverSocket.accept();
System.out.println("GOT CONNECTION");
PlayerThread playerThread = new PlayerThread(clientSocket);
playerThread.start();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Exception occured on server");
break;
}
}
This is PlayerThread loop:
while (true) {
try {
String inputMessage = in.readUTF();
System.out.println("GOT: " + inputMessage);
JsonNode jsonNode = objectMapper.readTree(inputMessage);
String senderName = jsonNode.get("senderName").asText();
if (!players.contains(this)) {
playerName = senderName;
players.add(this);
}
for (PlayerThread p : players) {
p.getOut().writeUTF(inputMessage);
}
And finally listening to messages:
public void listen() {
if (connected) {
try {
if (in.available() > 0) {
String inputMessage = in.readUTF();
System.out.println("GOT MESSAGE: " + inputMessage);
handleMessages(inputMessage);
}
} catch (IOException e) {
LOGGER.log(Level.INFO, "Connection lost");
connected = false;
}
} else
LOGGER.log(Level.INFO, "Player is not connected");
}
Method above is run in main game loop. It checks if there's something in inputStream and then reads it.
This is how correct message looks like:
GOT MESSAGE: {"type":"UPDATE_STATE","content":null,"senderName":"GRACZ 52","posX":10.0,"posY":5.0}
It works ok when there are 2 players, but the more players connect the more probably is to get message like this (or similiar broken messages):
GOT MESSAGE: 0} U{"type":"UPDATE_STATE","content":null,"senderName":"GRACZ 65","posX":10.0,"posY":5.0}
or
GOT MESSAGE: {"type":"UPDATE_STATE","content":null,"senderName":"GRACZ 24","pos
There different errors in message like Y letter, half-message or multiple messages in one row. Why such thing happen? It looks like when there are more players and they write into output stream in server side, this stream is not read yet so they are appending and appending. But it doesn't explain why there are broken and most imporant, how to resolve it?
I can move reading stream to another thread because in.readUTF() locks process but I wanted to keep it synchronized in main game loop and I don't think this will help (am I wrong?)
You need to synchronize your write loop on an object that's common between all PlayerThreads so that messages don't interleave.
synchronized(/*Should be a "global" server object*/) {
for (PlayerThread p : players) {
p.getOut().writeUTF(inputMessage);
}
}

Only works in debugging mode

I'm trying to create a program for a distributed system. At the moment I have a thread for listening to connections, and a thread for sending, and a thread for receiving.
I've reached a problem where the client will connect but only when using breakpoints. I can't figure out the problem at all!. I've tried to implement things to slow the program down however nothing is working.
If you guys could take a look i'd be greatly appreciative.
public static void main(String[] args)
{
System.out.println("Server starting on port 5000");
RecievingConnection reciever = new RecievingConnection(5000,0); //Recieving Connection
reciever.start();
SendingConnection sender = new SendingConnection(5001,1); //Sending Connection
sender.start();
while(true){
while(reciever.ready==true){
System.out.println("In");
nodes first = new nodes(reciever.socket,0);
System.out.println("Node created");
first.start();
System.out.println("Client connected on port: " + reciever.socket.getLocalAddress());
nodes second = new nodes(sender.socket,1);
second.start();
reciever.ready=false;
sender.ready=false;
reciever.connectionComplete=true;
sender.connectionComplete=true;
}
}
}
public RecievingConnection(int port, int mode)
{
Serverport = port;
connectionMode = mode;
try{
server = new ServerSocket(port);
server.setSoTimeout(100000);
}
catch(IOException ex)
{
System.out.println(ex);
}
}
public void run(){
while(true){
if(ready == false){
try {
socket = server.accept();
ready = true;
System.out.println("Attempting to connect using port: " + Serverport);
while(connectionComplete == false){
//wait
}
} catch (IOException ex) {
System.out.println(ex);
}
}
}
}
The sending thread is basically the same code. Any idea what the problem is? "Nodes" is the thread for each node.
I solved it by adding a sleep in the main thread. I presume this is because the main thread takes priority over child threads?
Your problem is almost certainly at:
while (connectionComplete == false) {
//wait
}
This will loop forever, the other thtreads will not get any cpu time at all. It also explains why it works in debug - it's because in debug if you stop at a breakpoint, any other threads will get time.
You should at least do:
while (connectionComplete == false) {
//wait
Thread.sleep(0);
}
and maybe use a number much greater than 0. This will allow other thtreads a chance to run.
I am not suggesting that this will make your code work correctly but it should remove the current problem.
After that there's another tight loop that won't let any other thread time.
while (true) {
if (ready == false) {
Change that to:
while (true) {
if (ready == false) {
// ...
} else {
// Here too.
Thread.sleep(0);
}
}
You can't just share variables between threads. Make them volatile, synchronize or use CAS types like AtomicBoolean.
Read about it.
https://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html
http://www.journaldev.com/1061/java-synchronization-and-thread-safety-tutorial-with-examples
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html
Besides class "nodes" is not described here and classes are expected to start with an upper case letter.

DatagramChannel.close() keeps port open on Windows

I'm implementing a Discover process that:
Open a UDP socket to listen for broadcast response on a given port
Send some requests (and expect later response)
Close the UDP socket after a given period of time
The first call works. But other call get a bind error. Address already in use: bind
I'm running Windows 7. I did some tests and found that after a channel.close(); Netstat still gives:
netstat -a -b -sp udp | grep 55224
UDP 0.0.0.0:55224 :
So the udp port is still opened at the OS level
I searched the web and it may be a leak at the os level : Some java Datagram Socket questions
I ran 2 tests one using NIO channel and one without (from a test found on the web). I reproduce my error with the NIO version but it works if I don`t use NIO.
I anybody can point me how I can make it works with NIO. The targetted platform is Android where I dont want to always listen for broadcast but only for repetitive period of time.
TEST SOCKET
public void testConnectCloseWithSocket() {
long tCumulative = 0;
int errAt = -1;
System.out.println("start...");
for (int i = 0; i < 4000; i++) {
try {
errAt = i;
DatagramSocket result = new DatagramSocket(null);
result.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
result.close();
//success at last
tCumulative = 0;
} catch (Exception e) {
System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());
tCumulative+=50;
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
}
i--;
}
}
System.out.println("end...");
}
RESULT SOCKET<
start...
Error (at=1319) (waited=0ms): Address already in use: Cannot bind
Error (at=1438) (waited=0ms): Address already in use: Cannot bind
Error (at=1587) (waited=0ms): Address already in use: Cannot bind
Error (at=1740) (waited=0ms): Address already in use: Cannot bind
end...
I did get some errors but the socket get closed properly... which is oki for my needs
TEST WITH CHANNEL
public void testConnectCloseWithChannel() {
long tCumulative = 0;
int errAt = -1;
System.out.println("start...");
for (int i = 0; i < 4000; i++) {
try {
errAt = i;
Selector selector = Selector.open();
DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(true);
channel.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
clientKey.cancel();
channel.close();
//success at last
tCumulative = 0;
} catch (Exception e) {
System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());
tCumulative+=50;
try {
Thread.sleep(tCumulative);
} catch (InterruptedException e1) {
}
i--;
}
}
System.out.println("end...");
}
NOTE: It the channel.register is commented the test works ..
RESULT WITH CHANNEL
start...
Error (at=0) (waited=0ms): null
Error (at=0) (waited=50ms): Address already in use: bind
Error (at=0) (waited=100ms): Address already in use: bind
Error (at=0) (waited=150ms): Address already in use: bind
...
Thanks for any help
I did get some errors but the socket get closed properly... which is
oki for my needs
No, in case you've got errors your channel is NOT closed properly.
You have to do close in the finally clause of your try block.
Selector selector = Selector.open();
try
{
DatagramChannel channel = DatagramChannel.open();
try
{
channel.configureBlocking(true);
channel.socket().bind(
new InetSocketAddress(InetAddress.getLocalHost(), 9005)
);
SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
clientKey.cancel();
}
finally
{
channel.close();
}
}
finally
{
selector.close( )
}
Some parts of a channel close are deferred to the next select() if the channel is registered with a Selector. It is documented somewhere in the forest of Selector, AbstractSelector, SelectorSpi, SelectableChannel, AbstractSelectableChannel, where I can never find it when I need it. If you're within the select loop and thread when you close the channel, you can make it immediate by calling selectNow().

Categories