I am trying to implement a WebSocketClient in Thread where Client is continuously sending message to the server, But I see Exception:
org.eclipse.jetty.websocket.api.WebSocketException: RemoteEndpoint
unavailable, current state [CLOSED], expecting [OPEN or CONNECTED]
here is the code:
public class ProcessAnalysisThread extends Thread {
static String dest = "ws://localhost:8086/Echo/";
WebSocketClient client;
EAMClientSocket socket;
public void run() {
initializeWSClient();
while (true) {
System.out.println("Thread running");
try {
Thread.sleep(500);
socket.sendMessage("echo");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void initializeWSClient() {
client = new WebSocketClient();
try {
socket = new EAMClientSocket(this);
client.start();
URI echoUri = new URI(dest);
System.out.println("URI Resolved");
ClientUpgradeRequest request = new ClientUpgradeRequest();
client.connect(socket, echoUri, request);
System.out.println("Connected and Waiting .....");
socket.getLatch().await();
System.out.println("Latched");
System.out.println("RequestURI: " + request.getRequestURI().toString());
socket.sendMessage("echo");
System.out.println("Sent Msg: echo");
socket.sendMessage("test");
System.out.println("Sent Msg: test");
// Thread.sleep(10000l);
} catch (Throwable t) {
System.out.println("Exception");
t.printStackTrace();
} finally {
try {
client.stop();
} catch (Exception e) {
System.out.println("Exception1");
e.printStackTrace();
}
}
}
}
Here is the output:
Connected and Waiting .....
Connected to server
Latched
RequestURI: ws://localhost:8086/Echo/
Sent Msg: echo
Sent Msg: test
Message received from server:echo
Message received from server:test
Thread running
Exception in thread "Thread-0" org.eclipse.jetty.websocket.api.WebSocketException: RemoteEndpoint unavailable, current state [CLOSED], expecting [OPEN or CONNECTED]
at org.eclipse.jetty.websocket.common.WebSocketSession.getRemote(WebSocketSession.java:252)
Looks like my thread not holding socket reference here
Related
Thanks for this opportunity to ask questions here.
Summary
I have a spring boot application which runs on Tomcat. I'm subscribing ActiveMQ topic with StompClient. After connected i get messages via StompHandler's handleFrame method.
In that method i create MessageUtils which implements Runnable interface. In MessageUtils run method, creating new thread with ExecutorService and do the task generateMessage which send messages to kafka topic.
Problem
When I shutdown the tomcat, threads are still alive. In catalina.out;
A web application appears to have started a thread named [foo] but has failed to stop it. This is very likely to create a memory leak
So the tomcat cannot shutdown properly.
Code Samples
#Service
StompService.class
#EventListener(ApplicationReadyEvent.class)
public void start() {
logI("Service run Client Methods");
List<String> topics = Arrays.asList(topicListString.split(","));
for (String topic : topics) {
StompClient client = new StompClient(topic, username, password, url, topic, bootstrapAddress);
try {
client.run();
runMap.put(topic, client);
boolean connected = client.getSession().isConnected();
logI("Topic: " + topic + " is connected: " + connected);
} catch (InterruptedException e) {
logE("InterruptedException during start of stomp client: ", e);
} catch (TimeoutException e) {
logE("TimeoutException during start of stomp client: ", e);
} catch (ExecutionException e) {
logE("ExecutionException during start of stomp client: ", e);
} catch (Exception e) {
logE("Unexpected exception during start of stomp client: ", e);
}
}
}
StompClient.class
public void run() throws ExecutionException, TimeoutException, InterruptedException {
WebSocketClient client = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(client);
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.afterPropertiesSet();
StompHeaders connectHeaders = new StompHeaders();
connectHeaders.add("login", this.userName);
connectHeaders.add("passcode", this.password);
stompClient.getDefaultHeartbeat();
stompClient.setTaskScheduler(taskScheduler);
stompClient.setMessageConverter(new StringMessageConverter());
stompClient.setAutoStartup(true);
StompSessionHandler sessionHandler = new StompHandler(this.topic, this.bootstrapAddress);
StompSession stompSession = null;
try {
stompSession = stompClient.connect(url, new WebSocketHttpHeaders(), connectHeaders, sessionHandler)
.get(5, TimeUnit.SECONDS);
} catch (Exception e) {
logE("Cannot connect with stomp client." , e);
}
this.setSession(stompSession);
}
StompHandler.class which extends StompSessionHandlerAdapter
#Override
public void handleFrame(StompHeaders headers, Object payload) {
String msg = (String) payload;
MessageUtils message = new MessageUtils();
message.setHeaders(headers);
message.setTopic(topic);
message.setMsg(msg);
message.setBootstrapAddress(bootstrapAddress);
message.run();
}
MessageUtils.class
#Override
public void run() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
generateMessage(getMsg().toString());
}
});
executorService.shutdown();
try {
executorService.awaitTermination(200, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
logI("InterruptedException during await termination", e);
}
}
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.
Imagine the next case:
Client - server connection
Client sends a request to the server
Server answers the Client
Client reads the answer
Class Client:
public class Client extends Service{
private String IP_ADDRESS;
private int PORT;
public void start(){
l.info("Starting client for server at: "+IP_ADDRESS+":"+PORT);
//Initialization of the client
try {
cs=new Socket(IP_ADDRESS,PORT);
} catch (UnknownHostException e) {
l.error("Unkown host at the specified address");
e.printStackTrace();
} catch (IOException e) {
l.error("I/O error starting the client socket");
e.printStackTrace();
}
}
//Sends the specified text by param
public void sendText(String text){
//Initializa the output client with the client socket data
try {
//DataOutputStream to send data to the server
toServer=new DataOutputStream(cs.getOutputStream());
l.info("Sending message to the server");
PrintWriter writer= new PrintWriter(toServer);
writer.println(text);
writer.flush();
} catch (IOException e) {
l.error("Bat initialization of the output client stream");
e.printStackTrace();
}
//Should show the answers from the server, i run this as a thread
public void showServerOutput(){
String message;
while(true){
//If there are new messages
try {
BufferedReader br= new BufferedReader(new InputStreamReader((cs.getInputStream())));
if((message=br.readLine())!=null){
//Show them
System.out.println(message);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
showServerOutput() is the method that returns any answer sent by the server
Then my server class have the following code
public class Server extends Service{
public void startListenner(){
l.info("Listening at port "+PORT);
while(true){
// Waits for a client connection
try {
cs=ss.accept();
l.info("Connection received: "+cs.getInetAddress()+":"+cs.getPort());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
toClient= new DataOutputStream(cs.getOutputStream());
PrintWriter cWriter= new PrintWriter(toClient);
//Send a confirmation message
cWriter.println("Message received");
//Catch the information sent by the client
csInput=new BufferedReader(new InputStreamReader(cs.getInputStream()));
printData();
toClient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
As you can see im sending a message to the client with the words: "Message received" but its never shown in the client console. Whats wrong?
EDIT
The printData() method prints the message received from the client in console
public void printData(){
l.info("Printing message received");
try {
System.out.println(csInput.readLine());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Not sure what your printData() method is doing, but aren't you missing a cWriter.flush() on the server side, once you printed "Message received" ?
As I understand it, you write your message but never send it to your client.
I have a socket listener thread in the client side which receives data from the server. Currently I'm just getting the data input stream from socket and reading data from the stream. I want to modify my listener thread in such way that processing of that thread is blocked until data is received in the socket instead of checking my input stream always.
My socket listener thread is given below
public void run() {
listenFlag = true;
try {
//instream is a global variable
inStream = new DataInputStream(clientSocket.getInputStream());
while (listenFlag) {
messageType = -1;
if (readHeader()) {// Check for correct header
Application.getLogger().log(Level.SEVERE, "<<< passed readHeader() ----");
if (readType()) {// Check for valid Type
Application.getLogger().log(Level.SEVERE, "<<< passed readType ----");
readAndProcessMessage();// Read and process the correct message
Application.getLogger().log(Level.SEVERE, "<<< passed readAndProcessMessage ----");
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
} catch (InterruptedException e) {
Application.getLogger().log(Level.SEVERE, "Interrupted socket communication - closing socket" + e.getMessage());
} catch (InterruptedIOException e) {
Application.getLogger().log(Level.SEVERE, "Interrupted IOException socket communication - closing socket" + e.getMessage());
} catch (IOException ioe) {
Application.getLogger().log(Level.SEVERE, "Socket read error : " + ioe.getMessage());
} catch (Exception e) {
Application.getLogger().log(Level.SEVERE, "Unknown exception on SocketListenThread:"+ e.getMessage());
} finally {
Application.getLogger().log(Level.SEVERE, "SocketListenThread: listenFlag : "+ listenFlag);
Application.getLogger().log(Level.SEVERE, "Quiting SocketListnerThread Thread");
DRISMCMStatus.socketListenerStatus = DRISMCMStatus.NOT_ALIVE;
closeInputStream();
}
}
//Read header called from above.
private boolean readHeader() throws Exception {
Application.getLogger().log(Level.INFO, "Reading header..");
DRISMCMStatus.socketListenerStatus = DRISMCMStatus.WAITING;
int val = inStream.read();
DRISMCMStatus.socketListenerStatus = DRISMCMStatus.RUNNING;
Application.getLogger().log(Level.INFO, "[READ]: " + val);
if (val == -1) {
throw new IOException();
}
if ( val == SYNCCHAR) {
return true;
}
return false;
}
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);
}
}
}
}