MqttBrowserClient fails to connect due to missing conack package - flutter

I am trying to make webapp over flutter which will connect to HIVE broker. I took the broker name from the official website, set the port number to 8000 just like mentioned there and still get the error message as below:
error is mqtt-client::NoConnectionException: The maximum allowed connection attempts ({1}) were exceeded. The broker is not responding to the connection request message (Missing Connection Acknowledgement?
I really have no clue how to proceed. Can someone please help?
Below is my code:
MqttBrowserClient mq = MqttBrowserClient(
'wss://broker.mqttdashboard.com:8000', '',
maxConnectionAttempts: 1);
/*
MqttBrowserClient mq = MqttBrowserClient('ws://test.mosquitto.org', 'client-1',
maxConnectionAttempts: 1);
*/
class mqttService {
Future<MqttBrowserClient?> connectToServer() async {
try {
final connMess = MqttConnectMessage()
.withClientIdentifier('clientz5tWzoydVL')
.authenticateAs('a14guguliye', 'z5tWzoydVL')
.withWillTopic('willtopic')
.withWillMessage('My Will message')
.startClean() // Non persistent session for testing
.withWillQos(MqttQos.atLeastOnce);
mq.port = 1883;
mq.keepAlivePeriod = 50;
mq.connectionMessage = connMess;
mq.websocketProtocols = MqttClientConstants.protocolsSingleDefault;
mq.onConnected = onConnected;
var status = await mq.connect();
return mq;
} catch (e) {
print("error is " + e.toString());
mq.disconnect();
return null;
}
}
}

That port 8000 may be open but the HiveMQ broker may not be listening.
Make sure that the broker is fully booted and binds to that IP:Port combo.
In the HiveMQ broker startup output, you should see something similar to:
Started Websocket Listener on address 0.0.0.0 and on port 8000
If needed, the HiveMQ Broker configuration documentation is here.
You can use the public HiveMQ MQTT Websocket demo client to test your connection to make sure it's not a local code issue.
As a last option, use Wireshark to monitor MQTT traffic with a filter of tcp.port == 8000 and mqtt

Related

Prevent nginx from killing idle tcp sockets

I'm trying to use nginx as a reverse proxy for ssl/tcp sockets (so that I can write my server custom as raw tcp, but have nginx handle the ssl certificates). My use case requires the tcp connections remain alive, but to go idle (no packets back and forth) for extended periods of time (determined by the client, but as long as an hour). Unfortunately, nginx kills my socket connections after the first 10 minutes (timed to within a second) of inactivity, and I haven't been able to find either online or in the docs what actually controls this timeout.
I know that it has to be nginx doing it (not my raw server timing out, or my client's ssl socket), since I can directly connect to the server's raw tcp server without timeout issues, but if I run nginx as a raw tcp reverse proxy (no ssl) it does timeout.
Here's some code to reproduce the issue, note that I've commented out the ssl relevent pieces in nginx because the timeout occurs either way.
/etc/nginx/modules-enabled/test.conf:
stream {
upstream tcp-server {
server localhost:33445;
}
server {
listen 33446;
# listen 33446 ssl;
proxy_pass tcp-server;
# Certs
# ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
}
server.js;
const net = require("net");
const s = net.createServer();
s.on("connection", (sock) => {
console.log('Got connection from', sock.remoteAddress, sock.remotePort );
sock.on("error", (err) => {
console.error(err)
clearInterval(i);
});
sock.on("close", () => {
console.log('lost connection from', sock.remoteAddress, sock.remotePort );
clearInterval(i);
});
});
s.listen(33445);
client.js
const net = require('net');
const host = 'example.com';
let use_tls = false;
let client;
let start = Date.now()
// Use me to circumvent nginx, and no timeout occurs
// let port = 33445;
// Use me to use nginx, and no timeouts occur after 10 mins of no RX/TX
let port = 33446;
client = new net.Socket();
client.connect({ port, host }, function() {
console.log('Connected via TCP');
// Include me, and nginx doesn't kill the socket
// setInterval(() => { client.write("ping") }, 5000);
});
client.on('end', function() {
console.log('Disconnected: ' + ((Date.now() - start)/1000/60) + " mins");
});
I've tried various directives in the nginx stream block, but nothing seems to help. Thanks in advance!

How to return error response to calling channel when TCP destination gives 'Connection refused'

I have this pattern:
channel ESANTE_MPI_CREATE_PATIENT_LISTENER (with a MLLP listener) calls channel ESANTE_MPI_CREATE_PATIENT that calls a TCP destination.
If connection cannot be done in the TCP destination inside ESANTE_MPI_CREATE_PATIENT then this channel reports an error for this destination:(ERROR: ConnectException: Connection refused (Connection refused))
The response transformer does not seem to be called (which is normal as there is no response).
I wonder how I can report the error back to the calling channel ESANTE_MPI_CREATE_PATIENT_LISTENER ?
PS: When tcp destination responds, then I use the response transformer to parse the received frame and create a response message (json error/ok) for the calling channel. Everything works fine here.
My question ends up with: How to trap a Connection refused in a TCP destination to create a response message.
I finally managed this by using the postprocessor script in ESANTE_MPI_CREATE_PATIENT to get the response of the connector and then force a message.
// fake error message prepared for connection refused.
// we put this as the response of the channel destination in order to force a understandable error message.
const sErrorMsg = {
status: "error",
error: "connection refused to eSanté MPI"
};
const TCP_CONNECTOR_ESANTE_MPI_RANK = 2; // WARNING: be sure to take the correct connector ID as displayed into destination.
const TCP_CONNECTOR_ESANTE_MPI_DNAME = 'd' + TCP_CONNECTOR_ESANTE_MPI_RANK; // WARNING: be sure to take the correct connector ID as displayed into destination.
/*
var cms = message.getConnectorMessages(); // returns message but as Immutable
responses. not what we want: we use responseMap instead.
var key = TCP_CONNECTOR_ESANTE_MPI_RANK;
logger.debug(" Response Data=" + cms.get(key).getResponseData());
logger.debug(" Response Data0=" + cms.get(key).getResponseError());
logger.debug(" Response Data1=" + cms.get(key).getResponseData().getError());
logger.debug(" Response Data2=" + cms.get(key).getResponseData().getMessage());
logger.debug(" Response Data3=" + cms.get(key).getResponseData().getStatusMessage());
logger.debug(" Response Data4=" + cms.get(key).getResponseData().getStatus());
*/
var responseMPI = responseMap.get(TCP_CONNECTOR_ESANTE_MPI_DNAME); // return a mutable reponse :-)
if (responseMPI.getStatus()=='ERROR' &&
responseMPI.getStatusMessage().startsWith('ConnectException: Connection refused')) {
// build a error message for this dedicated case
logger.error("connection refused detected");
responseMPI.setMessage(JSON.stringify(sErrorMsg)); // force the message to be responsed.
}
return;

Sending a message to a Kafka Broker using TCP Sockets and Deno

We are trying to create a Kafka client using Deno and TCP sockets. As a first step, we are trying to ping a broker we have running on a docker instance using the below code:
import {
Client,
Packet,
Event,
} from 'https://deno.land/x/tcp_socket#0.0.1/mods.ts';
const client = new Client({
hostname: 'localhost',
port: 9092,
});
for (let i = 0; i < 2; i++) {
// Connection open
client.on(Event.connect, (client: Client) => {
console.log('Connect', client.conn?.remoteAddr);
});
// Receive message
client.on(Event.receive, (client: Client, data: Packet) => {
console.log('Receive', data.toString());
});
// Connection close
client.on(Event.close, (client: Client) => {
console.log('Close');
});
// Handle error
client.on(Event.error, (e) => {
console.error(e);
});
// Do
await client.connect(); // Start client connect
await client.write('Hello World'); // Send string data
await client.write(new Uint8Array()); // Send Uint8Array data
client.close();
}
We are successfully pinging the broker, but receive the following error:
[2021-08-13 00:20:36,472] WARN Unexpected error from /172.20.0.1; closing connection (org.apache.kafka.common.network.Selector)
org.apache.kafka.common.network.InvalidReceiveException: Invalid receive (size = 1214606444 larger than 104857600)
at org.apache.kafka.common.network.NetworkReceive.readFromReadableChannel(NetworkReceive.java:91)
at org.apache.kafka.common.network.NetworkReceive.readFrom(NetworkReceive.java:71)
at org.apache.kafka.common.network.KafkaChannel.receive(KafkaChannel.java:169)
at org.apache.kafka.common.network.KafkaChannel.read(KafkaChannel.java:150)
at org.apache.kafka.common.network.Selector.pollSelectionKeys(Selector.java:365)
at org.apache.kafka.common.network.Selector.poll(Selector.java:313)
at kafka.network.Processor.poll(SocketServer.scala:494)
at kafka.network.Processor.run(SocketServer.scala:432)
at java.lang.Thread.run(Thread.java:745)
[2021-08-13 00:28:19,708] INFO [Group Metadata Manager on Broker 0]: Removed 0 expired offsets in 0 milliseconds. (kafka.coordinator.GroupMetadataManager)
We understand that this is due to a protocol issue and are trying to determine what the best way forward is to address this issue. Any help would be greatly appreciated

Spring cloud eureka client to multiple eureka servers

I am able to get the eureka server to operate in a peer to peer mode. But one thing I am curious about is how do I get a service discovery client to register to multiple eureka servers.
My use case is this:
Say I have a service registering to one of the eureka servers (e.g. server A) and that registration is replicated to its peer. The service is actually pointing at server A. If server A goes down, and the client expects to renew with server A, how do the renewal work if server A is no longer present.
Do I need to register with both and if not then how does the renewal happen if the client cannot communicate with server A. Does it have some knowledge of server B (from its initial and/or subsequent comms with A) and fail over to do its registration renewal there? That is not clear in any of the docs and I need to verify
So based on the answer, I added the following to my application.yml
eureka:
# these are settings for the client that gets services
client:
# enable these two settings if you want discovery to work
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:8762/eureka/, http://localhost:8761/eureka/
It only registers to the first in the comma separated list. If I switch them around the registration flips between eureka servers.
I can see that it does separate these based on comma but my guess is that Eureka does not use this underneath (from EurekaClientConfigBean.java)
#Override
public List<String> getEurekaServerServiceUrls(String myZone) {
String serviceUrls = this.serviceUrl.get(myZone);
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = this.serviceUrl.get(DEFAULT_ZONE);
}
if (serviceUrls != null) {
return Arrays.asList(serviceUrls.split(","));
}
return new ArrayList<>();
}
I just reviewed the source code for Eureka 1.1.147. It works differently that i expected but at least I know now.
You can put multiple service urls in the set
serviceUrl:
defaultZone: http://localhost:8762/eureka/, http://localhost:8761/eureka/
But the register action only uses the first one to register. There remaining are used only if attempting to contact the first fails.
from (DiscoveryClient.java)
/**
* Register with the eureka service by making the appropriate REST call.
*/
void register() {
logger.info(PREFIX + appPathIdentifier + ": registering service...");
ClientResponse response = null;
try {
response = makeRemoteCall(Action.Register);
isRegisteredWithDiscovery = true;
logger.info(PREFIX + appPathIdentifier + " - registration status: "
+ (response != null ? response.getStatus() : "not sent"));
} catch (Throwable e) {
logger.error(PREFIX + appPathIdentifier + " - registration failed"
+ e.getMessage(), e);
} finally {
if (response != null) {
response.close();
}
}
}
which calls
private ClientResponse makeRemoteCall(Action action) throws Throwable {
return makeRemoteCall(action, 0);
}
It only calls the backup when an exception is thrown in the above makeRemoteCall(action, 0) call
} catch (Throwable t) {
closeResponse(response);
String msg = "Can't get a response from " + serviceUrl + urlPath;
if (eurekaServiceUrls.get().size() > (++serviceUrlIndex)) {
logger.warn(msg, t);
logger.warn("Trying backup: " + eurekaServiceUrls.get().get(serviceUrlIndex));
SERVER_RETRY_COUNTER.increment();
return makeRemoteCall(action, serviceUrlIndex);
} else {
ALL_SERVER_FAILURE_COUNT.increment();
logger.error(
msg
+ "\nCan't contact any eureka nodes - possibly a security group issue?",
t);
throw t;
}
So you can't really register to two eureka servers simultaneously from this code. Unless I missed something.
Your client application should be provided a list of Eureka URLs. The URLs are comma separated.
Yes, as per the documentation, the flow is:
client registers to the first available eureka server
registrant information is replicated between eureka server nodes.
So multiple registration is not only not needed but should be avioded.
Please add below property in application.property or application.yml file
eureka.client.service-url.defaultZone = http://localhost:8761/eureka,http://localhost:8762/eureka
Services will be registered with both eureka server.If one eureka server is down then request will be served from other eureka server.
If you want to a workaround to register on multiple eureka servers.
please review my answer on similar question: https://stackoverflow.com/a/60714917/7982168

how to check if connection is established when use libev with non-block socket

I have some code use libev on how to deal with connection timeout as below (please refer to http://lists.schmorp.de/pipermail/libev/2011q2/001365.html):
sd = create_socket()
set_socket_nonblock(sd)
connect("127.0.0.1", port) // connect to an invalid port
ev_io_init(&w_io, connect_cb, sd, EV_WRITE)
ev_io_start(...)
ev_timer_init(&w_timer, timeout_cb, 5.0, 0)
ev_timer_start(...)
and in someplace perform ev_run. The connect_cb is called and in this callback function I checked the revents with EV_ERROR, the result is no error. This is strange because I provide an invalid port number which is not listening in local machine. Anyway, I try to send a message in the connect_cb function, got an error 111, which means that connection refused. I'm confused! How to check if the connection is established correctly when use non-block socket?
getsockopt is possible way to get if the connection has some error happen:
int err;
socklen_t len = sizeof(err);
getsockopt(sd, SOL_SOCKET, SO_ERROR, &err, &len);
if (err) {
// error happen
} else {
connection is OK
}