This is the piece of code I am facing issues with. When the post construct gets called..the source gets set .. But when I receive a message from server and the processBinaryMessage method gets called..the source turns out to be null.
I don't understand the problem...Any help is appreciated..
#ClientEndpoint
#Component
public class MyClientEndpoint {
#Inject
private Source Source;
private boolean postConstructCalled = false;
#PostConstruct
public void init() {
postConstructCalled = true;
System.out.println("Post construct called ... ");
}
#OnOpen
public void onOpen(Session session) {
System.out.println("Connected to endpoint: " + session.getBasicRemote());
SessionUtil.setSession(session);
try {
System.out.println("Checking the established connection........");
session.getBasicRemote().sendText("Checking the connection...");
} catch (IOException ex) {
Logger.getLogger(MyClientEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
}
#OnMessage
public void processMessage(String message) {
System.out.println("Received string message in client: " + message);
}
#OnMessage
public void processBinaryMessage(byte[] bytes) {
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byte[] type = new byte[3];
byteBuffer.get(type);
String msgType = new String(type);
//System.out.println("Read type : " + msgType);
if(msgType.compareTo("MAX") == 0) {
int maxLimit = byteBuffer.getInt();
System.out.println("Read max blocks : " + maxLimit);
ClientDataTransfer.setMaxTransferLimit(maxLimit);
}
else if(msgType.compareTo("NXT") == 0) {
ClientDataTransfer.incMaxTransferLimit();
}
else if(msgType.compareTo("MAP") == 0) {
int length = byteBuffer.getInt();
byte[] data = new byte[length];
byteBuffer.get(data);
source.getClientDataTransfer().addToDataRequestQueue(data);
}
}
#OnError
public void processError(Throwable t) {
t.printStackTrace();
}
#OnClose
public void onClose(Session session) {
try {
session.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Closing connection to endpoint: " + session.getBasicRemote());
}
}
Thanks,
Sreeja
Related
I have a simple rmi-server and rmi-client. When i run this server and client in same network, my server function returns the result properly. But my server and client are in different networks and if the process time is more than 3-4 minutes client can not get the result, although server fihishes the operation.
here is my entire server code:
public class SimpleServer {
ServerRemoteObject mRemoteObject;
public static int RMIInPort = 27550;
public static int delay = 0;
public byte[] handleEvent(byte[] mMessage) throws Exception {
String request = new String(mMessage, "UTF-8");
// if ("hearthbeat".equalsIgnoreCase(request)) {
// System.out.println("returning for hearthbeat");
// return "hearthbeat response".getBytes("UTF-8");
// }
System.out.println(request);
Thread.sleep(delay);
System.out.println("returning response");
return "this is response".getBytes("UTF-8");
}
public void bindYourself(int rmiport) {
try {
mRemoteObject = new ServerRemoteObject(this);
java.rmi.registry.Registry iRegistry = LocateRegistry.getRegistry(rmiport);
iRegistry.rebind("Server", mRemoteObject);
} catch (Exception e) {
e.printStackTrace();
mRemoteObject = null;
}
}
public static void main(String[] server) {
int rmiport = Integer.parseInt(server[0]);
RMIInPort = Integer.parseInt(server[1]);
delay = Integer.parseInt(server[2]);
System.out.println("server java:" + System.getProperty("java.version"));
System.out.println("server started on:" + rmiport + "/" + RMIInPort);
System.out.println("server delay on:" + delay);
SimpleServer iServer = new SimpleServer();
iServer.bindYourself(rmiport);
while (true) {
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
and here is my client code:
public class SimpleClient {
ISimpleServer iServer;
public SimpleClient(String p_strServerIp, String p_strCMName, int nRMIPort) {
try {
if (nRMIPort == 1099) {
iServer = (ISimpleServer) Naming.lookup("rmi://" + p_strServerIp + "/" + p_strCMName);
} else {
Registry rmiRegistry = null;
rmiRegistry = LocateRegistry.getRegistry(p_strServerIp, nRMIPort);
iServer = (ISimpleServer) rmiRegistry.lookup(p_strCMName);
}
} catch (Exception ex) {
ex.printStackTrace();
iServer = null;
}
}
public static void main(String... strings) {
String ip = strings[0];
int rmiport = Integer.parseInt(strings[1]);
System.out.println("client java:" + System.getProperty("java.version"));
System.out.println("client is looking for:" + ip + ":" + rmiport);
SimpleClient iClient = new SimpleClient(ip, "Server", rmiport);
try {
byte[] response = iClient.iServer.doaction("this is request".getBytes("UTF-8"));
System.out.println(new String(response, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
and here is my rmi-registry code:
public class SimpleRMI implements Runnable {
Registry mRegistry = null;
public SimpleRMI(int nPort) {
try {
mRegistry = new sun.rmi.registry.RegistryImpl(nPort);
} catch (RemoteException e1) {
e1.printStackTrace();
}
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(360000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String... strings) {
int rmiport = Integer.parseInt(strings[0]);
System.out.println("rmi java:" + System.getProperty("java.version"));
System.out.println("rmi started on:" + rmiport);
SimpleRMI iRegisry = new SimpleRMI(rmiport);
Thread tThread = new Thread(iRegisry);
tThread.start();
byte[] bytes = new byte[1];
while (true) {
try {
System.in.read(bytes);
if (bytes[0] == 13) {
try {
iRegisry.listRegistry();
} catch (Exception exc2) {
exc2.printStackTrace();
}
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
private void listRegistry() {
String[] strList = null;
try {
strList = mRegistry.list();
if (strList != null) {
for (int i = 0; i < strList.length; i++) {
int j = i + 1;
String name = strList[i];
java.rmi.Remote r = mRegistry.lookup(name);
System.out.println(j + ". " + strList[i] + " -> "
+ r.toString());
}
}
System.out.println();
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
and my remote interface and remote object:
public interface ISimpleServer extends java.rmi.Remote {
public byte[] doaction(byte[] message) throws java.rmi.RemoteException;
}
#SuppressWarnings("serial")
public class ServerRemoteObject extends UnicastRemoteObject implements ISimpleServer {
SimpleServer Server = null;
public ServerRemoteObject(SimpleServer pServer) throws RemoteException {
super(SimpleServer.RMIInPort);
Server = pServer;
}
#Override
public byte[] doaction(byte[] message) throws RemoteException {
try {
return Server.handleEvent(message);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
when i run client and server in different networks. (i run client in my home network) and if delay is more than 3-4 mins server prints returning response but client still waits for the response. If delay is only 1 minute, clients gets the result properly.
Can you please help me to find where the problem is?
I am trying to run the below code I am getting EOFException. The below is my output
Connected to ssl://REMOVED.messaging.internetofthings.ibmcloud.com:8883
.deliveryComplete() entered
Data published on topic iot-2/type/loradevice/id/cdef1234/cmd/cid/fmt/json and the msg is{"count":0,"cmd":"reset","time":"2017-01-25 18:38:34"}
connection true
Connection lost (32109) - java.io.EOFException
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:267)
at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)
... 1 more
The code is below
package com.ibm.bluemixmqtt;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.json.JSONException;
import org.apache.commons.json.JSONObject;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
public class AppTest2
{
private MqttHandler1 handler;
/**
* #param args
*/
public static void main(String[] args)
{
new AppTest2().doApp();
}
/**
* Run the app
*/
public void doApp()
{
// Read properties from the conf file
Properties props = MqttUtil.readProperties("Mydata\\app.conf");
String org = "REMOVED";
String id = "REMOVED";
String authmethod = "REMOVED";
String authtoken = "REMOVED";
// isSSL property
String sslStr = props.getProperty("isSSL");
boolean isSSL = false;
if (sslStr.equals("T")) {
isSSL = true;
}
System.out.println("org: " + org);
System.out.println("id: " + id);
System.out.println("authmethod: " + authmethod);
System.out.println("authtoken" + authtoken);
System.out.println("isSSL: " + isSSL);
// Format: a:<orgid>:<app-id>
String clientId = "a:" + org + ":" + id;
String serverHost = org + MqttUtil.SERVER_SUFFIX;
handler = new MqttHandler1();
handler.connect(serverHost, clientId, authmethod, authtoken, isSSL);
publish();
}
public void publish(){
JSONObject jsonObj = new JSONObject();
String deviceid = "cdef1234";
try {
jsonObj.put("cmd", "reset");
jsonObj.put("count", 0);
jsonObj.put("time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
} catch (JSONException e) {
e.printStackTrace();
}
handler.publish(
"iot-2/type/" + MqttUtil.DEFAULT_DEVICE_TYPE + "/id/" + deviceid + "/cmd/" + MqttUtil.DEFAULT_CMD_ID + "/fmt/json",
jsonObj.toString(), false, 0);
}
}
class MqttHandler1 implements MqttCallback
{
private final static String DEFAULT_TCP_PORT = "1883";
private final static String DEFAULT_SSL_PORT = "8883";
private MqttClient client = null;
public MqttHandler1()
{
}
#Override
public void connectionLost(Throwable throwable)
{
if (throwable != null) {
System.out.println("Error3");
throwable.printStackTrace();
}
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken)
{
System.out.println(".deliveryComplete() entered");
}
#Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception
{
String payload = new String(mqttMessage.getPayload());
System.out.println(".messageArrived - Message received on topic " + topic + ": message is " + payload);
}
public void connect(String serverHost, String clientId, String authmethod, String authtoken, boolean isSSL)
{
// check if client is already connected
if (!isMqttConnected()) {
String connectionUri = null;
// tcp://<org-id>.messaging.internetofthings.ibmcloud.com:1883
// ssl://<org-id>.messaging.internetofthings.ibmcloud.com:8883
if (isSSL) {
connectionUri = "ssl://" + serverHost + ":" + DEFAULT_SSL_PORT;
} else {
connectionUri = "tcp://" + serverHost + ":" + DEFAULT_TCP_PORT;
}
if (client != null) {
try {
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
client = null;
}
try {
client = new MqttClient(connectionUri, clientId);
} catch (MqttException e) {
e.printStackTrace();
}
client.setCallback(this);
// create MqttConnectOptions and set the clean session flag
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(authmethod);
options.setPassword(authtoken.toCharArray());
options.setKeepAliveInterval(2000);
// If SSL is used, do not forget to use TLSv1.2
if (isSSL) {
java.util.Properties sslClientProps = new java.util.Properties();
sslClientProps.setProperty("com.ibm.ssl.protocol", "TLSv1.2");
options.setSSLProperties(sslClientProps);
}
try {
// connect
client.connect(options);
System.out.println("Connected to " + connectionUri);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
public void disconnect()
{
// check if client is actually connected
if (isMqttConnected()) {
try {
// disconnect
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
}
public void subscribe(String topic, int qos)
{
// check if client is connected
if (isMqttConnected()) {
try {
client.subscribe(topic, qos);
System.out.println("Subscribed: " + topic);
} catch (MqttException e) {
e.printStackTrace();
}
} else {
connectionLost(null);
}
}
public void unsubscribe(String topic)
{
// check if client is connected
if (isMqttConnected()) {
try {
client.unsubscribe(topic);
} catch (MqttException e) {
e.printStackTrace();
}
} else {
connectionLost(null);
}
}
public void publish(String topic, String message, boolean retained, int qos)
{
// check if client is connected
if (isMqttConnected()) {
// create a new MqttMessage from the message string
MqttMessage mqttMsg = new MqttMessage(message.getBytes());
// set retained flag
mqttMsg.setRetained(retained);
// set quality of service
mqttMsg.setQos(qos);
try {
client.publish(topic, mqttMsg);
System.out.println("Data published on topic " + topic + " and the msg is" + mqttMsg);
System.out.println("connection "+client.isConnected());
} catch (MqttPersistenceException e) {
System.out.println("Error1");
e.printStackTrace();
} catch (MqttException e) {
System.out.println("Error1");
e.printStackTrace();
}
} else {
connectionLost(null);
}
}
private boolean isMqttConnected()
{
boolean connected = false;
try {
if ((client != null) && (client.isConnected())) {
connected = true;
}
} catch (Exception e) {
// swallowing the exception as it means the client is not connected
}
return connected;
}
}
Any one help me on this.
Thanks in adavance.
the EOFException might indicates that the clientID is reused and the access is blocked... make sure that you only call once the connect method... possibly use only the SSL or non-SSL connection sequence
I am trying to communicate with an external TCP server using TcpOutboundGateway and a client TcpConnectionFactory. In my scenario, each connection should be associated with different thread (each connection on the thread might be used for more then one request/response).
So I used a ThreadAffinityClientConnectionFactory from this topic: Spring Integration tcp client multiple connections
It worked fine until I tried to open more than 4 concurrent connections, the fifth (and over) connection is failing on timeout.
I figured out that org.springframework.integration.ip.tcp.TcpOutboundGateway uses semaphore in handleRequestMessage method to acquire a connection, so I overridden TcpOuboundGateway like this:
public class NoSemaphoreTcpOutboundGateway extends TcpOutboundGateway {
private volatile AbstractClientConnectionFactory connectionFactory;
private final Map<String, NoSemaphoreTcpOutboundGateway.AsyncReply> pendingReplies = new ConcurrentHashMap();
#Override
public boolean onMessage(Message<?> message) {
String connectionId = (String)message.getHeaders().get("ip_connectionId");
if(connectionId == null) {
this.logger.error("Cannot correlate response - no connection id");
this.publishNoConnectionEvent(message, (String)null, "Cannot correlate response - no connection id");
return false;
}
if(this.logger.isTraceEnabled()) {
this.logger.trace("onMessage: " + connectionId + "(" + message + ")");
}
NoSemaphoreTcpOutboundGateway.AsyncReply reply = (NoSemaphoreTcpOutboundGateway.AsyncReply)this.pendingReplies.get(connectionId);
if(reply == null) {
if(message instanceof ErrorMessage) {
return false;
} else {
String errorMessage = "Cannot correlate response - no pending reply for " + connectionId;
this.logger.error(errorMessage);
this.publishNoConnectionEvent(message, connectionId, errorMessage);
return false;
}
} else {
reply.setReply(message);
return false;
}
}
#Override
protected Message handleRequestMessage(Message<?> requestMessage) {
connectionFactory = (AbstractClientConnectionFactory) this.getConnectionFactory();
Assert.notNull(this.getConnectionFactory(), this.getClass().getName() + " requires a client connection factory");
TcpConnection connection = null;
String connectionId = null;
Message var7;
try {
/*if(!this.isSingleUse()) {
this.logger.debug("trying semaphore");
if(!this.semaphore.tryAcquire(this.requestTimeout, TimeUnit.MILLISECONDS)) {
throw new MessageTimeoutException(requestMessage, "Timed out waiting for connection");
}
haveSemaphore = true;
if(this.logger.isDebugEnabled()) {
this.logger.debug("got semaphore");
}
}*/
connection = this.getConnectionFactory().getConnection();
NoSemaphoreTcpOutboundGateway.AsyncReply e = new NoSemaphoreTcpOutboundGateway.AsyncReply(10000);
connectionId = connection.getConnectionId();
this.pendingReplies.put(connectionId, e);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Added pending reply " + connectionId);
}
connection.send(requestMessage);
//connection may be closed after send (in interceptor) if its disconnect message
if (!connection.isOpen())
return null;
Message replyMessage = e.getReply();
if(replyMessage == null) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Remote Timeout on " + connectionId);
}
this.connectionFactory.forceClose(connection);
throw new MessageTimeoutException(requestMessage, "Timed out waiting for response");
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Response " + replyMessage);
}
var7 = replyMessage;
} catch (Exception var11) {
this.logger.error("Tcp Gateway exception", var11);
if(var11 instanceof MessagingException) {
throw (MessagingException)var11;
}
throw new MessagingException("Failed to send or receive", var11);
} finally {
if(connectionId != null) {
this.pendingReplies.remove(connectionId);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Removed pending reply " + connectionId);
}
}
}
return var7;
}
private void publishNoConnectionEvent(Message<?> message, String connectionId, String errorMessage) {
ApplicationEventPublisher applicationEventPublisher = this.connectionFactory.getApplicationEventPublisher();
if(applicationEventPublisher != null) {
applicationEventPublisher.publishEvent(new TcpConnectionFailedCorrelationEvent(this, connectionId, new MessagingException(message, errorMessage)));
}
}
private final class AsyncReply {
private final CountDownLatch latch;
private final CountDownLatch secondChanceLatch;
private final long remoteTimeout;
private volatile Message<?> reply;
private AsyncReply(long remoteTimeout) {
this.latch = new CountDownLatch(1);
this.secondChanceLatch = new CountDownLatch(1);
this.remoteTimeout = remoteTimeout;
}
public Message<?> getReply() throws Exception {
try {
if(!this.latch.await(this.remoteTimeout, TimeUnit.MILLISECONDS)) {
return null;
}
} catch (InterruptedException var2) {
Thread.currentThread().interrupt();
}
for(boolean waitForMessageAfterError = true; this.reply instanceof ErrorMessage; waitForMessageAfterError = false) {
if(!waitForMessageAfterError) {
if(this.reply.getPayload() instanceof MessagingException) {
throw (MessagingException)this.reply.getPayload();
}
throw new MessagingException("Exception while awaiting reply", (Throwable)this.reply.getPayload());
}
NoSemaphoreTcpOutboundGateway.this.logger.debug("second chance");
this.secondChanceLatch.await(2L, TimeUnit.SECONDS);
}
return this.reply;
}
public void setReply(Message<?> reply) {
if(this.reply == null) {
this.reply = reply;
this.latch.countDown();
} else if(this.reply instanceof ErrorMessage) {
this.reply = reply;
this.secondChanceLatch.countDown();
}
}
}
}
the configurations of SpringContext looks like this:
#Configuration
#ImportResource("gateway.xml")
public class Conf {
#Bean
#Autowired
#ServiceActivator(inputChannel = "clientOutChannel")
public NoSemaphoreTcpOutboundGateway noSemaphoreTcpOutboundGateway(ThreadAffinityClientConnectionFactory cf, DirectChannel clientInChannel){
NoSemaphoreTcpOutboundGateway gw = new NoSemaphoreTcpOutboundGateway();
gw.setConnectionFactory(cf);
gw.setReplyChannel(clientInChannel);
gw.setRequestTimeout(10000);
return gw;
}
<int-ip:tcp-connection-factory
id="delegateCF"
type="client"
host="${remoteService.host}"
port="${remoteService.port}"
single-use="true"
lookup-host="false"
ssl-context-support="sslContext"
deserializer="clientDeserializer"
serializer="clientSerializer"
interceptor-factory-chain="clientLoggingTcpConnectionInterceptorFactory"
using-nio="false"/>
The delegateCF is passed to ThreadAffinityClientConnectionFactory constructor
So, the question is:
Is it OK to use NoSemaphoreTcpOutboundGateway in conjunction with ThreadAffinityClientConnectionFactory in terms of concurrency?
Looks like you go right way, but at the same time I think you don't need custom TcpOutboundGateway. The semaphore logic is based on the:
if (!this.isSingleUse) {
logger.debug("trying semaphore");
if (!this.semaphore.tryAcquire(this.requestTimeout, TimeUnit.MILLISECONDS)) {
throw new MessageTimeoutException(requestMessage, "Timed out waiting for connection");
}
at the same time look at Gary's solution for the ThreadAffinityClientConnectionFactory:
#Bean
public TcpNetClientConnectionFactory delegateCF() {
TcpNetClientConnectionFactory clientCF = new TcpNetClientConnectionFactory("localhost", 1234);
clientCF.setSingleUse(true); // so each thread gets his own connection
return clientCF;
}
#Bean
public ThreadAffinityClientConnectionFactory affinityCF() {
return new ThreadAffinityClientConnectionFactory(delegateCF());
}
Pay attention to the comment. Only you need is delegate isSingleUse().
I currently have a problem while working with Mina. I am able to create a NIOAcceptor and Connector and connect the client to the server. Upon session being created in the Server, it sends the handshake packet which in turn validates and sends back validation to the server to see if files are up-to-date, etc. The server receives this validation and correctly deciphers the packet and sends the packet to the Client to display the game window. However, after this initial connection, I can no longer send packets to the server via the Client.
ServerHandler:
#Override
public void sessionOpened(IoSession session) {
log.info("[Login] to [" + GameConstants.GAME_NAME + ": IoSession with {} opened", session.getRemoteAddress());
Client c = new Client(session);
connectedClients.add(session.getRemoteAddress().toString());
session.setAttribute(Client.KEY, c);
c.write(PacketCreator.getHandshake());
// c.write(PacketCreator.getPing());
}
#Override
public void messageReceived(IoSession session, Object message) {
PacketReader reader = new PacketReader((byte[]) message);
Client c = (Client) session.getAttribute(Client.KEY);
short header = reader.readShort();
PacketHandler handler = PacketProcessor.getHandler(header);
System.out.println("Received opcode: 0x" + Integer.toHexString(header).toUpperCase());
if (handler != null) {
handler.handlePacket(reader, c);
} else {
log.info("Received opcode: 0x" + Integer.toHexString(header).toUpperCase() + " with no handler.");
}
}
#Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("session error");
}
#Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("Session closing: " + session.getRemoteAddress().toString());
connectedClients.remove(session.getRemoteAddress().toString());
Client c = (Client) session.getAttribute(Client.KEY);
if (c != null) {
c.disconnect();
c.dispose();
} else {
log.warn("Client is null in sessionClosed for ip {} when it shouldn't be", session.getRemoteAddress());
}
super.sessionClosed(session);
}
ClientHandler:
#Override
public void sessionOpened(IoSession session) {
System.out.println("Session opened: " + session);
Server s = new Server(session);
session.setAttribute(Server.KEY, s);
s.write(PacketCreator.getPong());
}
#Override
public void messageReceived(IoSession session, Object message) {
PacketReader reader = new PacketReader((byte[]) message);
Server s = (Server) session.getAttribute(Server.KEY);
short header = reader.readShort();
PacketHandler handler = PacketProcessor.getHandler(header);
if (handler != null) {
handler.handlePacket(reader, s);
} else {
log.info("Received opcode: 0x" + Integer.toHexString(header).toUpperCase() + " with no handler.");
}
}
#Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("session error");
log.error("Exception caught in Server Handler: ", cause);
}
#Override
public void sessionClosed(IoSession session) throws Exception {
// TODO
System.out.println("session closed");
super.sessionClosed(session);
}
Client (NIOConnection class):
public static void connectToServer() throws Throwable {
NioSocketConnector connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(1000 * 30); // 30 seconds
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
connector.setHandler(new ClientHandler());
IoSession session;
long startTime = System.currentTimeMillis();
for (;;) {
try {
ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", 9494)); // 24.7.142.74
future.awaitUninterruptibly();
session = future.getSession();
break;
} catch (RuntimeIoException e) {
log.error("Failed to connect", e);
Thread.sleep(5000);
}
}
session.getCloseFuture().awaitUninterruptibly();
}
Server (NIOAcceptor class):
private static void initializeLoginServer() {
PacketProcessor.registerHandlers();
acceptor = new NioSocketAcceptor();
// acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));// TODO: encoding/decoding packets
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
acceptor.getSessionConfig().setTcpNoDelay(true);
acceptor.setHandler(new ServerHandler(1));
try {
acceptor.bind(new InetSocketAddress(GameConstants.SERVER_PORT));
} catch (Exception e) {
log.error("Could not bind. ", e);
}
log.info("Login Server: Listening on port " + GameConstants.SERVER_PORT);
}
I have written a mqtt client using paho mqttv3
This is the code for the client:
public class MQTT_Client {
private MqttClient mqtt;
private MqttConnectOptions conOpt;
private static Logger log = Logger.getRootLogger();
private String topicFilter;
private int connectionTimeout = 30;
public MQTT_Client(String brokerUrl) {
this.topicFilter = "/bmpiips/+/hb/out";
try {
String clientId = "HBA";
mqtt = new MqttClient(brokerUrl, clientId, new MemoryPersistence());
log.info("Connecting to " + brokerUrl + " with client ID " + mqtt.getClientId());
conOpt = new MqttConnectOptions();
conOpt.setCleanSession(true);
mqtt.setCallback(new MQTT_Callback(this));
} catch (MqttException e) {
log.error(null, e);
}
}
public void start() {
reconnect();
try {
subscribe(topicFilter, 1);
} catch (MqttException e) {
log.warn("Unable to subscribe to " + topicFilter);
}
}
private void connect() throws MqttSecurityException, MqttException {
if (mqtt.isConnected() == false) {
mqtt.connect(conOpt);
if (mqtt.isConnected() == true) {
log.info("Connected to MQTT Broker.");
}
}
}
public boolean isConnected() {
return mqtt.isConnected();
}
public boolean publish(String topicName, byte[] payload, int qos) {
try {
MqttTopic topic = mqtt.getTopic(topicName);
MqttMessage message = new MqttMessage(payload);
message.setQos(qos);
log.info("Publishing to topic: \"" + topicName + "\" Message size: " + payload.length + " bytes");
MqttDeliveryToken token = topic.publish(message);
token.waitForCompletion();
return true;
} catch (MqttException e) {
log.error(null, e);
return false;
}
}
public void subscribe(String topicName, int qos) throws MqttSecurityException, MqttException {
mqtt.subscribe(topicName, qos);
log.info("Subscribed to topic \"" + topicName + "\"");
}
public void reconnect() {
if (mqtt.isConnected() == false) {
try {
connect();
} catch (MqttSecurityException e) {
log.error("Coud not reconnect...", e);
} catch (MqttException e) {
log.error("Coud not reconnect...", e);
}
} else {
log.error("Allready connected...");
}
}
public void disconnect() throws MqttException {
mqtt.disconnect();
while (mqtt.isConnected()) {
// wait for disconnection
}
if (mqtt.isConnected() == false) {
log.info("Disconnected from the MQTT Broker.");
}
}
public String getTopicFilter() {
return topicFilter;
}
public int getConnectionTimeout() {
return connectionTimeout;
}
}
and this is the code for the callback class:
public class MQTT_Callback implements MqttCallback {
private static Logger log = Logger.getRootLogger();
private static MQTT_ThreadPool threadPool = new MQTT_ThreadPool();
private final MQTT_Client mqtt;
public MQTT_Callback(MQTT_Client mqtt) {
this.mqtt = mqtt;
}
#Override
public void connectionLost(Throwable cause) {
log.error("Disconnected from MqttBroker", cause);
while (mqtt.isConnected() == false) {
try {
log.info("Sleeping for : " + mqtt.getConnectionTimeout() + " seconds...");
Thread.sleep(mqtt.getConnectionTimeout() * 1000);
} catch (InterruptedException e) {
log.error("Coud not sleep...");
}
mqtt.reconnect();
try {
mqtt.subscribe(mqtt.getTopicFilter(), 1);
} catch (MqttException e) {
log.error(e);
}
}
}
#Override
public void deliveryComplete(MqttDeliveryToken token) {
log.info("Message delivered successfully");
}
#Override
public void messageArrived(MqttTopic topic, MqttMessage message) throws Exception {
log.info("Message received from topic: " + topic.getName() + " Message size: " + message.getPayload().length
+ " bytes");
threadPool.execute(topic, message);
}
}
It works ok but from time to time I get a weird exception that kills the connection:
2013-07-09 10:36:05.959 ERROR root:23 - Disconnected from MqttBroker
Connection lost (32109) - java.io.EOFException
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:119)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(Unknown Source)
at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:51)
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:86)
... 1 more
If anyone has ever come across this please give me some tips.