I am using a Netty server in linux with one netty client in Android. (Netty 4.0.23).
It works perfect most of the time. However, sometimes, my client is not able to connect to server.
The ChannelFuture received when trying to connect tells me that connection is done but not success (with cause not null) so it is completed with failure.
About the failure I received it is a java.net.socketException - EHOSTUNREACH error (No route to host).
I am quite sure that the problem is not in server.
Important:
I always run the server and the client in the same lan wifi network
with local ip addresses.
I have tested it in two different wifi
networks. In one of them, the reported error occurs rarely and in the
other occurs quite often.
CONNECT_TIMEOUT_MILLIS is configured with enough time in both contexts
I attach the way I do the connection from client:
.............
final ChannelFuture futureConnection = bootstrap.connect(HOST, PORT);
futureConnection.awaitUninterruptibly();
if (futureConnection.isDone()){
if (futureConnection.isCancelled()) {
// log error
}
else if (futureConnection.isDone() && futureConnection.isSuccess()){
// do something
}
else if (futureConnection.isDone() && (futureConnection.cause() != null)) {
// log error THIS IS THE ERROR REPORTED
}
else {
// log error
}
}
............
Related
I have developed a Quarkus app with which I want to receive and process MQTT messages.
This also works so far.
My problem is that when the internet goes down at the MQTT broker and the app reconnects afterwards, the app reconnects to the broker but no messages are received. I think that the "subscribe" method is not called anymore.
How can I solve this problem?
Here is my Config:
mp.messaging.incoming.smarthome/electricity.connector=smallrye-mqtt
mp.messaging.incoming.smarthome/electricity.host=192.168.1.88
mp.messaging.incoming.smarthome/electricity.port=1883
mp.messaging.incoming.smarthome/electricity.reconnect-attempts=3000
mp.messaging.incoming.smarthome/electricity.reconnect-interval-seconds=10
mp.messaging.incoming.smarthome/electricity.qos=1
mp.messaging.incoming.smarthome/electricity.failure-strategy=ignore
Here is my Controller:
#Incoming("smarthome/electricity")
public void consume(byte[] raw) {
String price = new String(raw,StandardCharsets.UTF_8);
String[] parts = price.split(",");
String watt = parts[0].trim();
String timeStamp = parts[1].trim();
byte wattH = Byte.parseByte(watt.replace("WH", ""));
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Vienna"))
.withHour(Integer.parseInt(timeStamp.split(":")[0]))
.withMinute(Integer.parseInt(timeStamp.split(":")[1]));
Message message = new Message(wattH,now);
System.out.println(message);
service.addToPackage(message);
scheudler.check();
}
Stack Output if i cut the Connection:
2022-09-20 07:50:09,683 ERROR [io.sma.rea.mes.mqtt] (vert.x-eventloop-thread-0) SRMSG17105: Unable to establish a connection with the MQTT broker: java.net.SocketException: Connection reset
If the Connection is back:
2022-09-20 07:50:26,751 INFO [io.ver.mqt.imp.MqttClientImpl] (vert.x-eventloop-thread Connection with 192.168.1.88:1883 established successfully
So the connection seems to be back, but there are no more incoming messages.
I solved the Problem by myself.
I set :
quarkus.arc.remove-unused-beans=none
And now it works fine.
I tried many ways to fix the problem, but this seems to be the issue.
I think there is some bean removed in the runtime when the connection is lost for a too long time.
If anyone can explain why this happens please tell me
We have an application hosted in a docker container calling a REST API, and we'd like to identify network timeouts and handle them in a specific way
Right now to detect timeouts we're using the following code snippet:
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
// do something...
}
While this did work in capturing some cases, when I setup an integration test where firewall/security groups was not configured correctly and the host isn't reachable, it resulted in the following error:
Post \"https://notreal.com/endpoint\": dial tcp 10.130.140.150:8443: i/o timeout
In this case it doesn't seem to fall under net.Error, and ideas on how else to identify this?
Edit:
Looks like this is an issue with our own libraries. The error was originally one that implemented net.Error but was swallowed, returning only the string and no longer implementing Timeout() or Temporary().
You have to implement it by yourself like you can see in this SO answer. However another way to this is to use an external package that will do that for you like retryablehttp.
resp, err := retryablehttp.Get("/foo")
if err != nil {
panic(err)
}
The returned response object is an *http.Response, the same thing you would usually get from net/http. Had the request failed one or more times, the above call would block and retry with exponential backoff.
If you need to distinguish transient errors from permanent errors (like endpoint that does not exist) you may try something like this (not tested by myself)?
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
// retry
}
if err != nil {
// unrecoverable error
log.Fatal(err)
}
Catching specific net errors can be tedious since there is a bunch of errors AddrError, DNSError and so on.
For testing, I've turned off networking. I've got caching disabled:
settings.isPersistenceEnabled = false // https://firebase.google.com/docs/firestore/manage-data/enable-offline -- done to help demonstrate async handling
I'm noticing that error is not set even though I see this in my logs:
2018-08-04 10:26:26.441529-0400 Behavior-based Notifications
prototype[52077:2250670] 5.4.1 - [Firebase/Firestore][I-FST000001]
Could not reach Cloud Firestore backend. Connection failed 2 times.
Most recent error: Error Domain=FIRFirestoreErrorDomain Code=2
"Network error (such as timeout, interrupted connection or unreachable
host) has occurred." UserInfo={NSLocalizedDescription=Network error
(such as timeout, interrupted connection or unreachable host) has
occurred.} This typically indicates that your device does not have a
healthy Internet connection at the moment. The client will operate in
offline mode until it is able to successfully connect to the backend.
Here's relevant code snippet:
DBIFirebase.db.collection(URI).getDocuments() {
(snapshot, error) in
if tx < 1 {
print("returned from Firebase TX when tx count is exhausted, dropping")
return
}
if let error = error {
// in either case, there was a previous error
print("Firestore error loading data for app \(app) - \(error.localizedDescription)")
callback(samples, Errors.firebaseError)
tx = 0
return
}
error is always nil. documents are always empty.
edit:
Very near after that if let error, I use this to process the documents:
guard let documents = snapshot?.documents else {
print("no documents for app \(app)")
callback(samples, nil)
tx = 0
return
}
for document in documents {
I set a breakpoint. error is seen to be nil. stepping into this block skips over it (the guard block doesn't trigger, I'm talking about stepping into from a breakpoint at the for loop). If I turn networking on, it goes into it (not a swifty caching loops thing).
How would I distinguish between an empty but successful return and a network connectivity issue?
I install kafka on a standalone server and try to stream data to mongodb.
when start kafka service, bin/kafka-server-start.sh config/server.properties
I had a warning:
WARN Attempting to send response via channel for which there is no open connection, connection id 0 (kafka.network.Processor)
Even though, there is no problem for data entered at producer and displayed at consumer.
but I think this cause the data write to mongodb. I have no data write to mongodb after start data streaming.
anyone can help with this issue? Thank you so much.
//processor.sendResponse
protected[network] def sendResponse(response: RequestChannel.Response) {
trace(s"Socket server received response to send, registering for write and sending data: $response")
val channel = selector.channel(response.responseSend.destination)
// `channel` can be null if the selector closed the connection because it was idle for too long
if (channel == null) {
warn(s"Attempting to send response via channel for which there is no open connection, connection id $id")
response.request.updateRequestMetrics()
}
else {
selector.send(response.responseSend)
inflightResponses += (response.request.connectionId -> response)
}
so, channel was closed by the selector because it was idle too long
I am trying to connect a dvr using boost asio library in ios. The application works fine in emulator with in ipv4 network. But when I submit the application on Appstore apple rejected the application as it's not work on ipv6 network. And I can see in the apple site that application should support ipv6 network. https://developer.apple.com/news/?id=05042016a
So I think the problem comes at the section where I am trying to connect to DVR using boost library, where the ip address of the DVR is pulled from DB(hard-coded) and below is the relevant part of the code.
boost::asio::io_service io_service_;
tcp::resolver::iterator endpoint_iter_;
tcp::resolver resolver_; //to healp resolving hostname and ip
stringstream strstream;//create a stringstream
strstream << port;//add number to the stream
endpoint_iter_ = resolver_.resolve(tcp::resolver::query(ip.c_str(),strstream.str()));
start_connect(endpoint_iter_);
// Start the deadline actor. You will note that we're not setting any
// particular deadline here. Instead, the connect and input actors will
// update the deadline prior to each asynchronous operation.
deadline_timer_.async_wait(boost::bind(&dvr_obj::check_deadline, this));
//starting thread for dvr connection
io_service_.reset();
thread_ = new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
start_connect method
void start_connect(tcp::resolver::iterator endpoint_iter)
{
try
{
if (endpoint_iter != tcp::resolver::iterator())
{
drill_debug_info("trying to connect %s \n",name.c_str());
// Set a deadline for the connect operation.
deadline_timer_.expires_from_now(boost::posix_time::seconds(10));
// Start the asynchronous connect operation.
socket_.async_connect(endpoint_iter->endpoint(),
boost::bind(&dvr_obj::handle_connect,
this, _1, endpoint_iter));
}
else
{
// There are no more endpoints to try. Shut down the client.
connectivity = false;
}
} catch (int e) {
connectivity = false;
}
}
So I am confused how to change above code to work on IPV6 network. Could not find any solution in Internet.
You can iterate through the endpoints to find an IPv6 endpoint using the code below:
endpoint_iter_ = resolver_.resolve(tcp::resolver::query(ip.c_str(),strstream.str()));
while (endpoint_iter_ != tcp::resolver::iterator())
{
if (endpoint_iter_->endpoint().protocol() == tcp::v6())
break;
++endpoint_iter_;
}
if (endpoint_iter_ != tcp::resolver::iterator())
{
start_connect(endpoint_iter_);
...
}
else
std::cerr << "IPv6 host not found" << std::endl;