I want to connect to a remote server from thread and keep sending strings. If the connection gets refused the thread should keep polling the port until the server is up again. How can I handle this exception and keep my thread fro crashing? The server may not be up for long time but thread should run indefinitely.
public void SendMessage(String message){
try {
socket = new Socket(actuatorAddress, destPort.get());
outToServer = socket.getOutputStream();
out = new DataOutputStream(outToServer);
out.flush();
out.write(message.getBytes());
} catch (IOException ex) {
System.out.println(ex.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
I changed some part of the code as below. For first time called Connect function and then subsequently called Send Message function through thread. The delay added to reconnecting helped reduce time lag recurred due to connecting to non existing server. Still think that there might be a better solution to the basic problem.
public boolean ConnectToActuator() {
try {
if(actuatorAddress.isReachable(2000)){
socket = new Socket();
socket.setPerformancePreferences(1, 2, 0);
socket.setTcpNoDelay(false);
socket.setSendBufferSize(32);
socket.connect(new InetSocketAddress(actuatorAddress, destPort.get()));
outToServer = socket.getOutputStream();
out = new DataOutputStream(outToServer);
connected = true;
disconnectedTimeout = 0;
}
}catch (ConnectException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}catch (IOException ex) {
connected = false;
System.out.println(ex.getMessage());
}
return connected;
}
public boolean SendToActuator(String message) {
if(connected == false){ //socket.isOutputShutdown()
disconnectedTimeout++;
if(disconnectedTimeout>20){
disconnectedTimeout = 0;
ConnectToActuator();
} else {
return connected;
}
}
try {
out.flush();
out.writeBytes(message);
disconnectedTimeout = 0;
connected = true;
} catch (UnknownHostException uhe) {
connected = false;
System.out.println(uhe.getMessage());
} catch (IOException ioe) {
connected = false;
System.out.println(ioe.getMessage());
}
return connected;
}
Given the following constraints in the comments:
Try to send the message to one of the 10 servers.
If none of the servers are available to receive the message, discard the message.
What you actually want to do is:
Iterate through a list of server addresses
Attempt to send a message to each of them
Break out of the loop right away if successful
Catch any errors on connection failure and try the next server
Here's an example class that will run through that scenario.
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
public class MessageSender {
private static final Integer destPort = 1234;
private static final String[] serverAddresses = {
"address1",
"address2",
"address3" // Etc....
};
public Boolean SendMessage(String message) {
Boolean messageSentSuccessfully = false;
for (String addy : serverAddresses) {
messageSentSuccessfully = SendMessageToServer(addy, message);
if (messageSentSuccessfully) {
break;
}
}
return messageSentSuccessfully;
}
private Boolean SendMessageToServer(String serverAddress, String message) {
Boolean messageSent = false;
try {
Socket dataSocket = new Socket(serverAddress, destPort);
OutputStream outToServer = dataSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.write(message.getBytes());
out.flush();
messageSent = true;
} catch (Exception e) {
System.out.println(e);
}
return messageSent;
}
}
Hope that helps.
Pseudo:
while(true){
if(connect()) DoClientConnectedStuff();
sleep(reconnectTimeout);
};
please try below changes. if your connection refuses it will wait for 2s(2000ms) and then again try to connect with server. if connection being successful it will take outputstream, write data in a while loop and flush the data.
public void createSocketConnection() throws IOException
{
socket = new Socket(actuatorAddress, destPort.get());
if(socket!=null)
{
outToServer = socket.getOutputStream();
out = new DataOutputStream(outToServer);
}
}
public void SendMessage(String message){
boolean isRunning=false;
try
{
createSocketConnection();
isRunning=true;
while(isRunning)
{
out.write(message.getBytes());
out.flush();
}
} catch (java.net.ConnectException conExcp) {
System.out.println(ex.getMessage());
try{
Thread.sleep(2000);
}catch(Exception ee){}
}
catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
Related
I want to transfer objects (AssignmentListener) from one Java Server to 5 Java Clients.
Therefore I wrote a method to send out the message:
private void sendMessage(AssignmentListener listener, int[] subpartitionIndices){
boolean success = false;
int failCount = 0;
// retry for the case of failure
while(!success && failCount < 10) {
try {
// get the stored socket & stream if stored
if(listener.getSocket() == null) {
if (localMode) {
listener.setSocket(new Socket("localhost", listener.getPort()));
} else {
listener.setSocket(new Socket(listener.getIp(), listener.getPort()));
}
listener.setOutputStream(new ObjectOutputStream(listener.getSocket().getOutputStream()));
}
AssignmentListenerMessage assignmentListenerMessage = new AssignmentListenerMessage(subpartitionIndices);
System.out.println("Sending " + assignmentListenerMessage);
listener.getOutputStream().writeObject(assignmentListenerMessage);
listener.getOutputStream().flush();
success = true;
} catch (IOException se) {
se.printStackTrace();
System.err.println("Failed to forward " + Arrays.toString(subpartitionIndices) + " to " + listener);
failCount++;
}
}
}
On the client side, I have the following:
public void run() {
String mode = "remote";
if(localMode) mode = "local";
// we need to register this listener at at the OverpartitioningManager
if(register(isLocalRequest)) System.out.println("Registered AssignmentListenerServer for index "+subpartitionIndex+" at ForwardingServer - "+mode);
running = true;
while (running) {
try {
socket = serverSocket.accept();
// Pass the socket to the RequestHandler thread for processing
RequestHandler requestHandler = new RequestHandler( socket );
requestHandler.start();
} catch (SocketException se) {
se.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
class RequestHandler extends Thread {
private Socket socket;
RequestHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Received a connection");
// Get input and output streams
inStream = new ObjectInputStream(socket.getInputStream());
//outStream = new DataOutputStream(socket.getOutputStream());
AssignmentListenerMessage incomingMessage = null;
while(socket.isBound()) {
try {
incomingMessage = (AssignmentListenerMessage) inStream.readObject();
}catch (StreamCorruptedException sce){
System.out.println("Failed to read AssignmentMessage from Stream, but will try again... (no ack)");
sce.printStackTrace();
continue;
}
// do stuff with the message
}
// Close our connection
inStream.close();
socket.close();
System.out.println("Connection closed");
} catch (Exception e) {
e.printStackTrace();
}
}
}
This works multiple times, but at one point I get the following exception:
java.io.StreamCorruptedException: invalid type code: 00
Does anyone have an idea or any other performance improvement for what I'm doing?
Thanks.
public class NewClass {
ServerSocket myServerSocket;
boolean ServerOn = true;
public NewClass() {
try {
myServerSocket = new ServerSocket(8888);
} catch (IOException ioe) {
System.out.println("Could not create server socket on port 8888. Quitting.");
System.exit(-1);
}
while (ServerOn) {
try {
Socket clientSocket = myServerSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException ioe) {
System.out.println("Exception found on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
try {
myServerSocket.close();
System.out.println("Server Stopped");
} catch (Exception ioe) {
System.out.println("Error Found stopping server socket");
System.exit(-1);
}
}
public static void main(String[] args) {
new NewClass();
}
class ClientServiceThread extends Thread {
Socket myClientSocket;
boolean m_bRunThread = true;
public ClientServiceThread() {
super();
}
ClientServiceThread(Socket s) {
myClientSocket = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
System.out.println(
"Accepted Client Address - " + myClientSocket.getInetAddress().getHostName());
try {
in = new BufferedReader(new InputStreamReader(myClientSocket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(myClientSocket.getOutputStream()));
while (m_bRunThread) {
String clientCommand = in.readLine();
if (clientCommand != null) {
System.out.println("Client Says :" + clientCommand);
}
if (!ServerOn) {
System.out.print("Server has already stopped");
out.println("Server has already stopped");
out.flush();
m_bRunThread = false;
}
if (clientCommand.equalsIgnoreCase("quit")) {
m_bRunThread = false;
System.out.print("Stopping client thread for client : ");
} else if (clientCommand.equalsIgnoreCase("end")) {
m_bRunThread = false;
System.out.print("Stopping client thread for client : ");
ServerOn = false;
} else {
out.println("Server Says : " + clientCommand);
out.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
out.close();
myClientSocket.close();
System.out.println("...Stopped");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Client Code
public class Client {
public static void main(String[] args) throws IOException {
Socket s = new Socket(InetAddress.getLocalHost(), 8888);
PrintWriter out =new PrintWriter(s.getOutputStream(), true);
out.print("KKKKKKKKKKKKK \r\n");
out.flush();
out.close();
}
The purpose of the above code is to create server socket and client socket to pass data between server and client.When the client sends the data to server .server grab the message and print it on the screen but with following exception.The pop up from the String clientCommand = in.readLine(); line which appeared on server code.
java.net.SocketException: Connection reset
Your code is invalid. Your server code relies on the client implementing the protocol correctly, which this client doesn't. Bad habit. Defensive coding is required. If clientCommand == null you must exit this read loop and close the socket. Your present code will attempt to write to the closed connection, which produces exactly this exception ... later.
I have a multithreaded tcp server, that handles multiple clients.
Each client has its thread on the serverside that keeps the socket connection.
Everything theoretically works fine for many minutes, but at rare occasions, while having multiple clients connected, the following happens:
One of the clients sends a tcp packet to the server and the serverside read times out. I have found many questions, that tackle read timeouts on the clientside, but in my case, this never happens. In my case, the server times out on a read when receiving a packet from a client.
My question is, why and how can this happen and what can I do to handle this problem?
here is my server listener:
public class GameServerTCP extends Thread {
//TCP
private ServerSocket serverSocket;
public Server server;
public int amountOfTCPConnections = 0;
ClassLoader classLoader = getClass().getClassLoader();
File myFile = new File(classLoader.getResource("Sprites/sprite_sheet.png").getFile());
public GameServerTCP(Server game) {
this.server = game;
//TCP
try {
serverSocket = new ServerSocket(6336);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
//TCP
Socket socket = null;
try {
socket = serverSocket.accept();
Toolkit.getDefaultToolkit().beep();
System.out.println(socket.getRemoteSocketAddress() + " has connected to server.");
}
catch (Exception e) {
e.printStackTrace();
}
new TCPConnection(socket, this);
amountOfTCPConnections++;
if (amountOfTCPConnections > 500) {
System.err.println("Too many clients error! (unsolved)");
server.frame.dispatchEvent(new WindowEvent(server.frame, WindowEvent.WINDOW_CLOSING));
}
}
}
}
here is my server thread that hold each single connection:
public class TCPConnection implements Runnable {
Socket socket;
private Thread thread;
private boolean isRunning = false;
public GameServerTCP serverTCP;
private String gamename = "-1";
public String username;
/**
* This is the future!
* Contains an exact imprint of the player of client side.
* Cheats can be detected here.
*/
private PlayerMP playerMP;
String clientSentence;
TCPConnection(Socket socket, GameServerTCP serverTCP) {
this.socket = socket;
this.serverTCP = serverTCP;
isRunning = true;
thread = new Thread(this);
thread.start();
}
public synchronized void closeConnection() {
if (MasterConnections.connectionsTCP.containsKey(getUniqueConnectionIdentifier())) MasterConnections.connectionsTCP.remove(getUniqueConnectionIdentifier());
if (this.username != null && MasterConnections.currentlyLoggedOnAccounts.contains(this.username)) MasterConnections.currentlyLoggedOnAccounts.remove(this.username);
if (this.gamename != null && serverTCP.server.games.containsKey(this.gamename)) {
Level game = serverTCP.server.games.get(this.gamename);
for (String p : game.playersInLevel) {
if (p.equals(getUniqueConnectionIdentifier())) {
game.playersInLevel.remove(p);
System.out.println(this.username + " has been been removed from game " + this.gamename + ".");
}
}
PacketTCP02LeaveGame tellOthersPacket = new PacketTCP02LeaveGame(this.gamename, this.username);
game.writeDataTCPToAllPlayersInThisLevel(tellOthersPacket);
}
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(socket.getRemoteSocketAddress() + " has been disconnected from server.");
this.serverTCP.amountOfTCPConnections--;
this.stop();
}
public String getUniqueConnectionIdentifier() {
return socket.getInetAddress() + ":" + socket.getPort();
}
public String generateUniqueUDPConnectionIdentifier(InetAddress inetAddess, int udpPort) {
System.out.println("uuc created: ");
System.out.println(inetAddess + "/" + udpPort);
return inetAddess + ":" + udpPort;
}
public void run() {
//version check first
PacketTCP00VersionCheck packetVersionCheck = new PacketTCP00VersionCheck(serverTCP.server.getVersion());
if (MasterConnections.connectionsTCP.containsKey(getUniqueConnectionIdentifier())) {
this.closeConnection();
}
else {
MasterConnections.connectionsTCP.put(getUniqueConnectionIdentifier(), this);
packetVersionCheck.writeData(this);
}
BufferedReader inFromClient;
try {
inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e1) {
e1.printStackTrace();
closeConnection();
return;
}
while(isRunning) {
try {
clientSentence = inFromClient.readLine();
if (clientSentence == null) {
inFromClient.close();
closeConnection();
}
else {
System.out.println("tcprec -> " + (new Date(System.currentTimeMillis())) + " -> " + this.username + " -> " + clientSentence);
this.parsePacket(clientSentence.getBytes());
}
}
catch (SocketTimeoutException ste) {
/**
* TODO:
*/
ste.printStackTrace();
System.err.println("YOU CAN DO SOMETHING HERE!!!!!!!");
closeConnection();
}
catch (Exception e) {
e.printStackTrace();
closeConnection();
}
}
}
public void stop() {
isRunning = false;
try {
thread.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And here is my client:
public class GameClientTCP extends Thread {
public String gamestate = "logged out";
private Game game;
public Socket tcpSocket;
public boolean isRunning = false;
private String serverSentence;
public boolean hasBeenStarted = false;
public int boundUDPPort = -1;
public static String[] characters = new String[5];
public static boolean charactersAreLoaded = false;
private PrintWriter toServer;
public GameClientTCP(Game game, String ipAddress) {
this.game = game;
}
public boolean tryConnect() {
try {
tcpSocket = new Socket();
tcpSocket.connect(new InetSocketAddress(Settings.SERVER_ADDRESS, 6336), 1000);
System.out.println("Just connected to " + tcpSocket.getRemoteSocketAddress());
game.getSocketClientUDP().prepareBeforeStart();
game.getSocketClientUDP().start();
return true;
} catch (UnknownHostException e1) {
try {
tcpSocket.close();
} catch (IOException e) {
GameError.appendToErrorLog(e);
return false;
}
return false;
} catch (IOException e1) {
try {
tcpSocket.close();
} catch (IOException e) {
GameError.appendToErrorLog(e);
return false;
}
GameError.appendToErrorLog(e1);
return false;
}
}
public void run() {
BufferedReader fromServer;
try {
fromServer = new BufferedReader(new InputStreamReader(tcpSocket.getInputStream()));
toServer = new PrintWriter(tcpSocket.getOutputStream(),true);
} catch (IOException e1) {
GameError.appendToErrorLog(e1);
return;
}
while(isRunning) {
try {
serverSentence = fromServer.readLine();
//System.out.println("Received: " + serverSentence);
if (serverSentence != null) this.parsePacket(serverSentence.getBytes());
}
catch(UnknownHostException ex) {
GameError.appendToErrorLog(ex);
}
catch(IOException e){
GameError.appendToErrorLog(e);
}
catch(Exception e) {
GameError.appendToErrorLog(e);
}
}
}
public void sendMessageToServer(String message) {
try {
toServer.println(message);
toServer.flush();
}
catch (Exception e) {
GameError.appendToErrorLog(e);
System.exit(-1);
}
}
}
I hope to find out more about this issue, please help! :)
EDIT: It may be important to say, that while my program is running, it can occur, that there are no tcp packets sent over a longer period of time. The timeout always happens, when i dont send any packets for at least 20 or 30 minutes and then when i send one again, another client times out.
As it turned out, tcp sockets, that are not used longer than a certain amount of time will be kind of destroyed by peers and therefore lose their connection.
I solved my issue, by sending a nearly empty tcp packet every minute to make it clear to all programs and services, that these sockets are alive!
I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code
String reader = (String)in.readObject();
an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive.
Anyway here is the entire source code :
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.
You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.
Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.
These resources would be helpful to you:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work
I got to stage where client and server communicate, sending messages from and to each other.
The problem I am having is how to close the connection without causing an error?
If I terminate one of the apps (either server or client) that causes the connection to be lost, and then it causes the loop that is waiting for input to loop indefinitely and showing null's.
I tried closing sockets, buffers and even the thread, didn't work.
This is the client side
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
This is the server side
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(
socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Both use these classes:
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(
this.clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
//***HERE EXTRA BIT FOR THE SERVER
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class updateUIThread implements Runnable {
private String msg;
public updateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
text.setText(msg);
}
}
the only difference is the server has this bit where it says above ***HERE EXTRA BIT FOR THE SERVER
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Message recieved");
so basically, client connects, server accepts, then client sends message, servers receives message and shows it, and then sends "Message received" to the client, and the client shows it.
All this works fine, but once the connection is lost, they hang on showing null repeatedly, and I have to force the app to close.
You aren't checking for end of stream. If readLine() returns null, the peer has closed the connection, and you must do likewise and stop reading.
It's hard to believe you really need a new thread for every line to update the UI.