how does WebSocketChannel warns that it disconnected? - dart

I am using WebSocketChannel as a socket server:
var handler = webSocketHandler((WebSocketChannel webSocket) async {
}
How can I know when the webSocket above gets disconnected?

You have to listen on the channel stream and intercept the close event with the onDone callback.
closeCode and closeReason properties give you details about the close.
webSocketHandler((channel) {
channel.stream.listen((data) {
channel.sink.add('Echo: $data');
},
onDone: () {
print('socket closed: reason=[${channel.closeReason}], code:[${channel.closeCode}]');
});
});

Even thought there is a correct answer to this thread, I ended up using another package for handling socket connections:
https://pub.dartlang.org/packages/socket_io

Related

How do I keep my script streaming so, it doesn't disconnecting?

So, I'm using filtered stream. Unfortunately, every time I turn it on, after 5 minutes its turns off but during that time, it catches tweets.
What I'm trying to do is keep it on 24/7 so, it doesn't turn off after 5 minutes. Also, if it disconnects I want it so, it tries connecting again.
This is the code sample I'm using to help adjust my code:
https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/master/Filtered-Stream/filtered_stream.js
function streamTweets(retryAttempt) {
const stream = needle.get(streamURL, {
headers: {
Authorization: `Bearer ${TOKEN}`
},
retryAttempt: 20000
});
stream.on('data', (data) => {
try {
const json = JSON.parse(data)
console.log(json.data.text)
retryAttempt = 0;
} catch (e) {
if (data.detail === "This stream is currently at the maximum allowed connection limit.") {
console.log(data.detail)
process.exit(1)
} else {
// Keep alive signal received. Do nothing.
}
}
}).on('err', error => {
if (error.code !== 'ECONNRESET') {
console.log(error.code);
process.exit(1);
} else {
// This reconnection logic will attempt to reconnect when a disconnection is detected.
// To avoid rate limits, this logic implements exponential backoff, so the wait time
// will increase if the client cannot reconnect to the stream.
setTimeout(() => {
console.warn("A connection error occurred. Reconnecting...")
streamTweets(++retryAttempt);
}, 2 ** retryAttempt)
}
});
return stream;
}
(async() => {
let currentRules;
try {
//get all stream rules
currentRules = await getRules();
//delete all stream rules
await deleteRules(currentRules);
//Set rules based on array above
await setRules();
} catch (e) {
console.error(e);
process.exit(1);
}
streamTweets(0);
})();
Have you tried to send the keepalive in your header?
Also, I changed the authorization header to match the syntax that of your linked GitHub code source.
function streamTweets(retryAttempt) {
const stream = needle.get(streamURL, {
headers: {
"authorization": `Bearer ${token}`,
"Connection": "keep-alive"
},
retryAttempt: 20000
});
Also, according to the Twitter docs: " If you would like to close your connection, you can press Control-C in your command line tool on either Mac or Windows systems to break the connection, or you can also close the window. "
Are you sure it's not disconnecting because you closed the terminal session, or was closed by something like an ssh timeout?

PhoneGap sockets-for-cordova quit app

I have a PhoneGap application and I want to open a socket to a endpoint using sockets-for-cordova plugin:
var socket = new Socket();
socket.open(
"192.168.2.1",
80,
function () {
// invoked after successful opening of socket
console.log("connection");
$scope.$apply();
},
function (errorMessage) {
// invoked after unsuccessful opening of socket
console.log("error");
$scope.$apply();
socket.shutdownWrite();
});
After I use this function to handle messages
socket.onData = function (data) {
// received message
}
On Android it works well, sending and receiving message, unfortunately on iOS it simply doesn't work, not receive any message at all or it close the socket itself.
I can see "connection" message, so I guess that the socket is created.

Connection time out using local broker

I've downloaded Mosca (^1.1.2), MQTT (via npm) and Paho. When I create a simple broker as shown here: http://thejackalofjavascript.com/getting-started-mqtt/ (last 3 codes). It works all fine. My problem is when I try to implement client in the browser using Paho. with this code:
// Create a client instance
var client = new Paho.MQTT.Client('127.0.0.1', 4883, "clientId-1");
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
var options = {
//connection attempt timeout in seconds
timeout: 3,
//Gets Called if the connection has successfully been established
onSuccess: function () {
console.log("onConnect");
client.subscribe("testtopic/#");
},
//Gets Called if the connection could not be established
onFailure: function (message) {
console.log("Connection failed: " + message.errorMessage);
}
};
// connect the client
client.connect(options);
// called when the client connects
function onConnect() {
console.log("onConnect");
client.subscribe("testtopic/#");
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
console.log(message.payload);
}
I always get this message: "Connection failed: AMQJSC0001E Connect timed out."
When I change '127.0.0.1' to a online broker, it works. So, I'm guessing my problem is with allowing ports in my broker.
Does anyone know how to solve this problem?

Exception ETIMEDOUT in node.js

I write application for iOS, which uses Socket.IO. Sometimes my server JS-script falls with this error:
events.js:85
throw er; // Unhandled 'error' event
^
Error: connect ETIMEDOUT
at exports._errnoException (util.js:746:11)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:983:19)
What I know is:
Script workes fine when I use only application for Android. That app uses Socket.IO for Android
Script workes fine when I use only web-client (yeap, with socket.IO)
Script startes to fall when I use iOS app.
Crash happens not always and not right away. Script falls after 5-10 minutes after connection and may crash, but may not.
So, I think the problem is in server library for socket.io, but exception fires only when iOS-client connecting.
How can I handle this exception?
UPDATE
There is problem was in the OAuth module on my node.js-server, which tried to check app token but had timeout to vk.com
I've edited vkapi module in my node.js server by adding "on" event for "https.get" function:
Was:
https.get(options, function(res) {
var apiResponse = new String();
res.setEncoding('utf8');
res.on('data', function(chunk) {
apiResponse += chunk;
});
res.on('end', function() {
var o = JSON.parse(apiResponse);
if (o.error) { self.emit('appServerTokenNotReady', o);
} else {
self.token = o.access_token;
self.emit('appServerTokenReady');
}
});
});
Now:
https.get(options, function(res) {
var apiResponse = new String();
res.setEncoding('utf8');
res.on('data', function(chunk) {
apiResponse += chunk;
});
res.on('end', function() {
var o = JSON.parse(apiResponse);
if (o.error) { self.emit('appServerTokenNotReady', o);
} else {
self.token = o.access_token;
self.emit('appServerTokenReady');
}
});
}).on('error', function(e) {
console.log('HTTPS error');
});
In general, you can handle these kinds of async errors by listening for the error event on whatever (e.g. request, connection, etc.) object.
The error event is special in that if there are currently no event handlers for it when it is emitted, the error will be thrown instead.

How to detect opening of a websocket connection from a controller

I have a controller (MyController), which requests data from a websocket connection (wsService) while initialising.
What is the best way to detect and wait that the websocket connection is open and then place the request from the controller?
Now I'm using following solution:
my_controller.dart:
MyController(wsService ws){
// when refresh() in wsService is called,
// the call is redirected to MyController's load()
ws.refresh = load;
}
load(){
ws.send(request);
}
ws_service.dart:
onConnect(){ //this is called when websocket connection is opened
refresh(); //this calls MyController's load()
}
I still think you should do something like this instead of make Angular polling the state.
MyController(wsService ws){
if(ws.readyState == WebSocket.OPEN) {
load();
} else {
ws.onOpen.first.then((_) => load());
}
}
load(){
ws.send(request);
}
This solution is still using polling, but with this solution the handling of websocket connection is kept in one place (wsService) and there is no duplicates in function calls.
MyController(wsService ws){
new Timer.periodic(new Duration(milliseconds: 100), (t){
if(ws.webSocket.readyState == WebSocket.OPEN) {
t.cancel();
load();
}
});
}
load(){
ws.send(request);
}

Resources