In our app, to communicate with the server we use MQTT Client. We use sockets only when the app is in Foreground mode, we may receive a lot of messages over Socket, thus we don't need to put Socket in Service.
How I can have the Socket Client in the background thread to send and receive messages, without freezing UI.
this is code of my Paho MQTT Socket Client:
mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), serverUri, clientId);
mqttAndroidClient.setCallback(new MqttCallbackExtended() {
#Override
public void connectComplete(boolean reconnect, String serverURI) {
if (reconnect) {
addToHistory("Reconnected to : " + serverURI);
// Because Clean Session is true, we need to re-subscribe
subscribeToTopic();
} else {
addToHistory("Connected to: " + serverURI);
}
}
#Override
public void connectionLost(Throwable cause) {
addToHistory("The Connection was lost.");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
addToHistory("Incoming message: " + new String(message.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
});
Related
I have a mosquitto broker running on my computer with mosquitto -v and I'm trying to connect to it from my android app. What I am doing is
public void connect() {
mqttAndroidClient = new MqttAndroidClient(context, "mqtt://192.168.1.198:1883", clientId);
mqttAndroidClient.setCallback(callback);
mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setCleanSession(false);
mqttAndroidClient.connect(mqttConnectOptions, context, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
disconnectedBufferOptions.setBufferEnabled(true);
disconnectedBufferOptions.setBufferSize(100);
disconnectedBufferOptions.setPersistBuffer(false);
disconnectedBufferOptions.setDeleteOldestMessages(false);
mqttAndroidClient.setBufferOpts(disconnectedBufferOptions);
Log.i(LOG_TAG, "Connected to the broker");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.e(LOG_TAG, "Not able to connect to the broker");
}
});
while(!mqttAndroidClient.isConnected()) {}
try {
mqttAndroidClient.subscribe("notify/new", 0);
} catch (MqttException ex) {
System.err.println("Exception whilst subscribing");
ex.printStackTrace();
}
}
But it never connects, because I don't see the "Connected to the broker" message and it gets in stuck in the while loop. What am I doing wrong?
As covered in the comments, the tight while loop checking if the client is connected is redundant as there is already a callback onSuccess() that can be used for that test.
The call to subscribe() should be moved into the callback.
The best way to handle subscribing to topics after the client is connected is to gate the call to subscribe() in an if block that checks the connected status. If that test fails add the topic to a global array, and call connect() again. The subscribe() in the onSuccess() callback should use the version that takes an array of topics
StreamObserver<RouteSummary> responseObserver = new StreamObserver<RouteSummary>() {
#Override
public void onNext(RouteSummary summary) {
LOGGER.info("Action.");
}
#Override
public void onError(Throwable t) {
LOGGER.error("Error.");
}
#Override
public void onCompleted() {
LOGGER.info("Completed.");
}
};
There is a grpc connection and client side streaming. Its started but If the Grpc Client is restarted,
how can I keep getting responses where they left off.
Client-side streaming means request streaming. Assuming you meant server side streaming, if the client is restarted it has basically lost the messages in the previous response stream.
in my code, there are four classes: mainProgram, Coordinator class, Client Class and Callback Class.
The mainProgram, which contains the main method of the program, creates an instance of the Coordinator Class and calls its start() method.
The later creates two instances of the Client Class, a publisher and a subscriber, connects both of them and subscribes one of the instances, the subscriber, to multiple topics.
The Client Class contains everything what has to do with mqtt and concerning the Callback for the subscribe-method, I've created an own class for this, the Callback Class which receives in the messageArrived method the incoming mqtt messages.
This is the code of the main:
public class mainProgram throws MqttException {
public static void main(String[] args) {
Coordinator coordinator=new Coordinator();
coordinator.start();
}}
this is the code of the Coordinator class:
public class Coordinator {
Client publisher;
Client subscriber;
public Coordinator() {
// TODO Auto-generated constructor stub
}
public void start() throws MqttException {
Client publisher=new Client("publisher","tcp://192.168.0.10",0);
publisher.connect();
Client subscriber=new Client("subscriber","tcp://192.168.0.10",0);
subscriber.connect();
subscriber.subscribeToTopic(new String [] {"home/Sensor2","home/Sensor3"});
}
public void getMessage(String message) throws MqttPersistenceException, MqttException {
publisher.publish("home/Sensor4", message);
}}
This is the Client Class:
public class Client {
String brokerAddress;
String clientId;
int qos;
MqttClient mqttClient;
MqttConnectOptions conOpt;
MemoryPersistence persistence;
Coordinator coordinator;
public Client(String clientId, String brokerAddress, int qos) {
this.clientId=clientId;
this.brokerAddress=brokerAddress;
this.qos=qos;
this.setConOpt();
}
public void setConOpt() {
conOpt=new MqttConnectOptions();
conOpt.setKeepAliveInterval(30);
conOpt.setAutomaticReconnect(false);
}
public void connect() throws MqttException {
mqttClient=new MqttClient(brokerAddress,clientId,persistence);
this.mqttClient.setCallback(new Callback(this));
this.mqttClient.connect(this.conOpt);
while(this.mqttClient.isConnected()==false) {
System.out.println("Connecting");
System.out.println("...");
}
if(this.mqttClient.isConnected()==true){
System.out.println("Der Mqttclient "+this.mqttClient.getClientId()+" is now connected!");
}
}
public void subscribeToTopic(String [] topics) throws MqttException {
for(int i=0;i<topics.length;i++) {
this.mqttClient.subscribe(topics[i]);
}
}
public void publish(String topic, String message) throws MqttPersistenceException, MqttException {
MqttMessage mqttMessage=new MqttMessage(message.getBytes());
this.mqttClient.publish(topic, mqttMessage);
}
}
This is the Callback Class:
public class Callback implements MqttCallback{
Client client;
public Callback(Client client) {
// TODO Auto-generated constructor stub
this.client=client;
}
#Override
public void connectionLost(Throwable arg0) {
// TODO Auto-generated method stub
System.out.println("Connection to server's lost");
}
#Override
public void deliveryComplete(IMqttDeliveryToken arg0) {
// TODO Auto-generated method stub
System.out.println("Message's delivered");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String ingoingMsg=message.toString();
System.out.println("until here all's fine");
Coordinator coordinator=new Coordinator();
coordinator.getMessage(ingoingMsg);
}
}
The program starts, creates the clients and when I publish via MQTTfx a message to the above mentionned topics, in the console this shows up:
The program ends and the connection of the client "subscriber" ends when I call the method "coordinator.getMessage()" and nothing is published.
At the end, the program should behave like this:
create clients
connect clients
subscribe the subscriber client
Listen and if a message to the topic subscribed is published: Call the getMessage of the coordinator class to publish something
while and after publishing the listening to further messages should not end and the programm is "in a loop" until the user breaks it up.
I searched everywhere for a solution, but there are not quite the same problems that I have on the web.
Maybe you have some illuminating tips for me ...
I am trying to play around with netty api using Netty Telnet server to check if the true asynchronous behaviour could be observed or not.
Below are the three classes being used
TelnetServer.java
public class TelnetServer {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new TelnetServerInitializer());
b.bind(8989).sync().channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
TelnetServerInitializer.java
public class TelnetServerInitializer extends ChannelInitializer<SocketChannel> {
private static final StringDecoder DECODER = new StringDecoder();
private static final StringEncoder ENCODER = new StringEncoder();
private static final TelnetServerHandler SERVER_HANDLER = new TelnetServerHandler();
final EventExecutorGroup executorGroup = new DefaultEventExecutorGroup(2);
public TelnetServerInitializer() {
}
#Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// Add the text line codec combination first,
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
// the encoder and decoder are static as these are sharable
pipeline.addLast(DECODER);
pipeline.addLast(ENCODER);
// and then business logic.
pipeline.addLast(executorGroup,"handler",SERVER_HANDLER);
}
}
TelnetServerHandler.java
/**
* Handles a server-side channel.
*/
#Sharable
public class TelnetServerHandler extends SimpleChannelInboundHandler<String> {
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// Send greeting for a new connection.
ctx.write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
ctx.write("It is " + new Date() + " now.\r\n");
ctx.flush();
ctx.channel().config().setAutoRead(true);
}
#Override
public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
// Generate and write a response.
System.out.println("request = "+ request);
String response;
boolean close = false;
if (request.isEmpty()) {
response = "Please type something.\r\n";
} else if ("bye".equals(request.toLowerCase())) {
response = "Have a good day!\r\n";
close = true;
} else {
response = "Did you say '" + request + "'?\r\n";
}
// We do not need to write a ChannelBuffer here.
// We know the encoder inserted at TelnetPipelineFactory will do the conversion.
ChannelFuture future = ctx.write(response);
Thread.sleep(10000);
// Close the connection after sending 'Have a good day!'
// if the client has sent 'bye'.
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
Now when i connect through telnet client and send commands hello hello hello three times
the request doesn't reach channelRead until first response to channelRead is being done is there any way i can make it asynchronous completely as to receive three hello as soon as they are available on socket.
Netty uses 1 thread max for every incoming read per handler, meaning that the next call to channelRead will only be dispatched after the previous call has been completed. This is required to for correct working of most handlers, including the sending back of messages in the proper order. If the amount of computation is really complex, another solution is using a custom thread pool for the messages.
If the other operation is instead a other kind of connection, you should use that as a async connection too. You can only get asynchronous if every part does this correctly.
I implementing websockets using Vert.x 3.
The scenario is simple: opening socket from client doing some 'blocking' work at the vertex verticle worker and when finish response with the answer to the client(via the open socket)
Please tell me if I am doing it right:
Created VertxWebsocketServerVerticle. as soon as the websocket is opening and request coming from the client I am using eventBus and passing the message to
EventBusReceiverVerticle. there I am doing blocking operation.
how I am actually sending back the response back to VertxWebsocketServerVerticle and sending it back to the client?
code:
Main class:
public static void main(String[] args) throws InterruptedException {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new EventBusReceiverVerticle("R1"),new DeploymentOptions().setWorker(true));
vertx.deployVerticle(new VertxWebsocketServerVerticle());
}
VertxWebsocketServerVerticle:
public class VertxWebsocketServerVerticle extends AbstractVerticle {
public void start() {
vertx.createHttpServer().websocketHandler(webSocketHandler -> {
System.out.println("Connected!");
Buffer buff = Buffer.buffer().appendInt(12).appendString("foo");
webSocketHandler.writeFinalBinaryFrame(buff);
webSocketHandler.handler(buffer -> {
String inputString = buffer.getString(0, buffer.length());
System.out.println("inputString=" + inputString);
vertx.executeBlocking(future -> {
vertx.eventBus().send("anAddress", inputString, event -> System.out.printf("got back from reply"));
future.complete();
}, res -> {
if (res.succeeded()) {
webSocketHandler.writeFinalTextFrame("output=" + inputString + "_result");
}
});
});
}).listen(8080);
}
#Override
public void stop() throws Exception {
super.stop();
}
}
EventBusReceiverVerticle :
public class EventBusReceiverVerticle extends AbstractVerticle {
private String name = null;
public EventBusReceiverVerticle(String name) {
this.name = name;
}
public void start(Future<Void> startFuture) {
vertx.eventBus().consumer("anAddress", message -> {
System.out.println(this.name +
" received message: " +
message.body());
try {
//doing some looong work..
Thread.sleep(10000);
System.out.printf("finished waiting\n");
startFuture.complete();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
I always get:
WARNING: Message reply handler timed out as no reply was received - it will be removed
github project at: https://github.com/IdanFridman/VertxAndWebSockets
thank you,
ray.
Since you are blocking your websocket handler until it receives a reply for the sent message to the EventBus, which will not, in fact, be received until the set up delay of 10s laps, you certainly will get warning since the reply handler of the event bus will timeout -> Message sent but no response received before the timeout delay.
Actually I don't know if you are just experimenting the Vert.x toolkit or you are trying to fulfill some requirement, but certainly you have to adapt your code to match in the Vert.x spirit:
First you should better not block until a message is received in your websocket handler, keep in mind that everything is asynchrounous when it comes to Vert.x.
In order to sleep for some time, use the Vert.x way and not the Thread.sleep(delay), i.e. vertx.setTimer(...).