read packet from tcp socket in java with acknoledgement - java

We are creating a java listener to read multiple device data those are configured on particular server ip and port.Device following below rule.
device send a login packet.
server will return ack packet in response.
after receive ack device will send information packet.
server reads that data.
on last step we stuck, we are sending the ack but cant get the information packet back from device(though we check the generated ack through opensource sofware).For ref we are attaching code.(if we remove while(true) than get login packet but after that socket connection will close and again device will send login packet but if we keep it then we dont get any packet)
//--------------Main class------------------------------------------
public class Main {
public static void main(String[] args) {
Server server = new Server(listen_port, pool_size, pm);
new Thread(server).start();
logger.info("Server Started .....");
}
}
//--------------------------------------------------------------
public class Server implements Runnable {
private ServerSocket serverSocket = null;
public void run()
{
this.m_stop = false;
while (!this.m_stop)
try {
this.m_pool.execute(new Handler(this.serverSocket.accept()));
} catch (IOException e) {
LOGGER.debug("Unable to accept connection ", e);
}
}
}
//--------------------------------------------------------------
public class Handler implements Runnable {
private Socket m_clientSocket;
private String imei;
public Handler(Socket socket) {
this.m_clientSocket = socket;
}
public void run() {
DataOutputStream clientDataOS = null;
DataInputStream clientDataIS = null;
try {
logger.info("data is coming");
m_clientSocket.setSoTimeout(300000);
clientDataIS = new DataInputStream(this.m_clientSocket.getInputStream());
clientDataOS = new DataOutputStream(this.m_clientSocket.getOutputStream());
while (true) {
String pkt = "";
logger.info("Waiting for input strem");
byte[] byte_pkt = IOUtils.toByteArray(clientDataIS);
logger.info("Got input stream");
for (byte b : byte_pkt) {
pkt += String.format("%02X ", b);
}
logger.info(pkt);
if (byte_pkt.length > 0) {
logger.info("");
if (Byte.valueOf(byte_pkt[3]) == 1) {
imei = "xyz";
logger.info("login packet");
byte[] rep_pkt = Utils.getReceptionPacket(byte_pkt);//send back to device
clientDataOS.write(rep_pkt);
clientDataOS.flush();
} else if (Byte.valueOf(byte_pkt[3]) == 34) {
logger.info("information packet");
Utils.processPackets(byte_pkt);
} else {
logger.info("Unkown packet format");
}
logger.info(imei);
} else {
logger.info("InputStream is empty.");
}
}
} catch (SocketException se) {
logger.error("Failure on reading data", se);
} catch (IOException e) {
logger.error("Failure on reading data", e);
} catch (Exception e) {
logger.error("Error while processing data", e);
} finally {
try {
IOUtils.closeQuietly(clientDataOS);
IOUtils.closeQuietly(clientDataIS);
this.m_clientSocket.close();
} catch (IOException e) {
logger.debug("Error when sending out response ::", e);
}
}
}
}

Related

java client server objects serialization: read objects in the same order they were sent

I'm developing a client server application in java. Communication takes place by serializing/deserializing immuable objects containing the information required, with ObjectOutputStream and ObjectInputStream.
In the server, every time I accept a new tcp connection, I instantiate a new Thread to handle the connection with that particular client.
This thread has a reference to the socket and it keeps reading objects:
while (true){
Object receivedObject = inputStream.readObject();
if (receivedObject instanceof MessageA){
//do sth
} else if (receivedObject instanceof MessageB){
//do sth else
}
this Runnable also has a method to send objects to the client:
public void sendMessage(Message message) {
try {
output.writeObject(message);
output.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
client-side, when the user enters the server's address, I instantiate a SocketClient object to handle the communication with the server:
public class SocketClient extends Observable {
private final Socket socket;
private final ObjectOutputStream outputStream;
private final ObjectInputStream inputStream;
private static int TIMEOUT = 5000;
public SocketClient(String serverAddress, int serverPort) throws IOException {
this.socket = new Socket();
this.socket.connect(new InetSocketAddress(serverAddress, serverPort), TIMEOUT);
this.outputStream = new ObjectOutputStream(socket.getOutputStream());
this.inputStream = new ObjectInputStream(socket.getInputStream());
}
public void readMessage() {
Thread readerThread = new Thread(() -> {
boolean read = true;
while (read) {
Message message;
try {
message = (Message) inputStream.readObject();
notifyObservers(message);
} catch (IOException | ClassNotFoundException e) {
message = new ErrorMessage(null, "Connection lost with the server.");
disconnect();
read = false;
}
}
});
readerThread.start();
}
public void sendMessage(Message message) {
try {
outputStream.writeObject(message);
outputStream.reset();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void disconnect() {
try {
socket.close();
} catch (IOException e) {
// disconnection error
e.printStackTrace();
}
}
}
messages are sent and received in both applications, the only problem is that when I send multiple messages sequentially in the server, they are sometimes received in a different order in the clients.
How may I fix that?

StreamCorruptedException after ~1000 transferred objects

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.

java.net.SocketException: Connection reset occurs from server socket

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.

Handling multi Java TCP clients with Threads

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

Connect to remote port(Server) from thread in polling

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

Categories