dart io websocket done not called when client disconnects - dart

I am trying to detect when a client has disconnected from the server. I thought that this was the correct way of doing it, but "someone disconnected" is never printed to the console.
import 'dart:io';
class VersusServer {
Future<void> run() async {
final PORT = 7171;
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, PORT);
server.forEach(_handleRequest);
print('Server listening on port $PORT.');
}
void _handleRequest(HttpRequest request) async {
if (request.uri.path == '/ws') {
var socket = await WebSocketTransformer.upgrade(request);
print('someone connected');
// MARK: this is the part I am trying to listen to disconnect
socket.done.then((value) => print('someone disconnected'));
socket.listen((message) {
print(message);
});
}
}
}
Is there something wrong in my code?
Thanks in advance!

Related

Ionic IOS project using SocketJS and Stomp Error : Whoops! Lost connection to 'URL'

I don't know why my Ionic socketjs service can run successfully in a browser but can not build connection when running as a IOS vm in Xcode.
Here's my socketjs service code. Can someone please help me with this, Thanks.
import { Injectable } from '#angular/core';
import { Observable, of } from 'rxjs';
import * as SockJS from 'sockjs-client';
import * as Stomp from 'stompjs';
#Injectable({
providedIn: 'root',
})
export class StompService {
private connecting: boolean = false;
private topicQueue: any[] = [];
options = {
timeout: 10000, // 设置超时时间为 10 秒
};
socket = new SockJS('http://44.211.141.255:8080/sba-websocket',undefined,this.options);
stompClient = Stomp.over(this.socket);
subscribe(topic: string, callback?: any): void {
// If stomp client is currently connecting add the topic to the queue
if (this.connecting) {
console.log("ing");
this.topicQueue.push({
topic,
callback
});
return;
}
console.log("2");
const connected: boolean = this.stompClient.connected;
if (connected) {
// Once we are connected set connecting flag to false
console.log("ed");
this.connecting = false;
this.subscribeToTopic(topic, callback);
return;
}
// If stomp client is not connected connect and subscribe to topic
this.connecting = true;
this.stompClient.connect({}, (): any => {
this.subscribeToTopic(topic, callback);
// Once we are connected loop the queue and subscribe to remaining topics from it
this.topicQueue.forEach((item:any) => {
this.subscribeToTopic(item.topic, item.callback);
})
// Once done empty the queue
this.topicQueue = [];
});
}
private subscribeToTopic(topic: string, callback?: any): void {
this.stompClient.subscribe(topic, (response?:string): any => {
console.log(response);
callback(response);
});
}
}
And here is the error message
[log] - Opening Web Socket...
[log] - Whoops! Lost connection to http://44.211.141.255:8080/sba-websocket
Help me fix the issue please

Is it possible in dart to put a certain key infront of your Socket ip

I have the following peer class
class Peer {
Peer({required this.count});
int count;
Future listen(String ip, int port) async {
ServerSocket ss = await ServerSocket.bind(ip, port);
ss.listen((client) {
print(client);
});
}
Future connect(String sstring) async {
final Socket s = await Socket.connect(
sstring.split(':')[0], int.parse(sstring.split(':')[1]));
await s.close();
}
}
and i was wondering if it was possible to put a certain key infront of my ip so it would listen on abc#127.0.0.1 instead of only 127.0.0.1

How to set timeout function for RawDatagramSocket in Dart

I have a Dart application which receives udp datagram every 10ms. I want to know when data stream is stopped. I have a RawDatagramSocket as _udpSocket I can listen datagram by using this function:
RawDatagramSocket? _udpSocket;
Future<void> bindSocket() async {
_udpSocket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, port);
setTimeout();
}
Future<void> listen() async {
_udpSocket?.listen((event) async {
Datagram? d = _udpSocket?.receive();
if (d == null) {
return;
}
//handle received data
});
}
And also I have a function to handle timeout:
void setTimeout() {
//if there is no data receiving in a couple of cycle, time out will be triggered.
//1 cycle == 10ms, I want timeout to be triggered after 10 cycles. (100ms)
_udpSocket?.timeout(timeoutDuration, onTimeout: (sink) {
//Handle time out
});
}
I am able to receive and process incoming data, but timeout function is not working.
Is there anything wrong with my code, or is there any other method to do what I want.
I figured it out,I updated the listen function. Here is the update for those who would need it:
final Duration timeoutDuration = const Duration(milliseconds: 100);
#override
Future<void> listen() async {
_udpSocket?.timeout(timeoutDuration, onTimeout: ((sink) {
//do your work when data stream closed
})).listen((event) async {
Datagram? d = _udpSocket?.receive();
if (d == null) {
return;
}
//handle received data
});
}
I hope it will be useful.

flutter socket.io client not working ~~~ helpme

I am making a chat app using flutter.
However, the socket connection does not work.
Port 80 is all connected locally, but sockets using aws are not connected.
I've tried both http and https, but no response. Help me!
Only the app does not connect, but the web connects.
The version of socket io client is 1.0.2, and the version of socket io is 2.3.0.
class _WebrtcState extends State<Webrtc> {
late final IO.Socket socket;
// late final SocketIO socketIO;
final _localRenderer = RTCVideoRenderer();
final _remoteRenderer = RTCVideoRenderer();
MediaStream? _localStream;
RTCPeerConnection? pc;
String check = "aafafasdfs";
#override
void initState() {
print('initState');
init();
super.initState();
}
Future init() async {
print('init');
await _localRenderer.initialize();
await _remoteRenderer.initialize();
await connectSocket();
await joinRoom();
}
Future connectSocket() async {
print('connectSocket');
socket = IO.io('http://********', IO.OptionBuilder().setTransports(['websocket']).build());
print(socket.opts);
socket.onConnect( (_){
print('connect');
setState(() {
check = "11111111111111111111ㅈ111";
});
});
socket.on('joined', (data) {
_sendOffer();
});
socket.on('offer', (data) async{
data = jsonDecode(data);
await _getOffer(RTCSessionDescription(data['sdp'], data['type']));
await _sendAnswer();
});
socket.on('answer', (data) {
data = jsonDecode(data);
_getAnswer(RTCSessionDescription(data['sdp'], data['type']));
});
socket.on('ice', (data) {
data = jsonDecode(data);
_getIce(RTCIceCandidate(data['candidate'], data['sdpMid'], data['sdpMLineIndex']));
});
}
}
To open a WebSocket connection, we need to create a new WebSocket using the special protocol ws in the URL:
final channel = WebSocketChannel.connect(
Uri.parse('wss://echo.websocket.org'),
);
There's also encrypted wss:// protocol. It's like HTTPS for WebSockets.
Please change the URL to something like the below form :
ws://********
wss://********

How do I register multiple handlers for a HttpServer, in Dart?

(I'm using the new lib v2 version of dart:io.)
I'd like to register multiple handlers for an HttpServer, specifically a WebSocketTransformer and other arbitrary handlers. Something like this:
// pseudo-code
var server = HttpServer;
server.register('/foo', someHandlerFunction); // 1
server.register('/bar', someOtherHandlerFunction); // 2
server.register('/ws', webSocketHandler); // 3
If #1 matches, then #2 isn't tested, and so on. So, it's greedy.
I've seen samples with just one handler. How do I register many handlers? Thanks in advance!
New answer: Use the route package: http://pub.dartlang.org/packages/route
Here's your example using route's serve() method:
HttpServer.bind('127.0.0.1', 8889).then((server) {
var router = new Router(server)
..serve('/ws').transform(new WebSocketTransformer()).listen(handleWebSocket)
..serve('/foo').listen((req) {
req.response..addString('foo')..close();
});
});
Router automatically catches unhandled requests and sends a 404, though soon you'll be able to override that with a defaultStream you can listen to.
Router also supports filters, useful for logging, auth, compression, etc.:
HttpServer.bind('127.0.0.1', 8889).then((server) {
var router = new Router(server)
..filter(new RegExp(r'/.*'), (req) {
//log all requests
_logger.info("request: $req");
return new Future.immediate(true); // keep processing request
})
..filter(new Regexp(r'/secure/.*'), (req) {
// check authentication asynchronously
return getUserFromRequest(req).then((user) {
if (user == null) {
sendRedirect('/login'); // sendRedirect coming soon
return false; // stop processing request
} else {
return true; // keep processing
}
});
})
..serve(/* ... */ );
});
Here's how the API docs recommend to register a WebSocket handler:
server
.where((request) => request.uri.path == "/ws")
.transform(new WebSocketTransformer()).listen((webSocket) => ...);
However, the server is a single-subscription stream. Once a listen is attached, you can't attach other listeners.
What I really want is for something to look at an event, decide if it can handle it, and if so then route it to another stream. Otherwise, pass it along. This way, the event (in this case an HttpRequest object) is passed along a chain until it's handled.
I built a TakeAndRoute class that extends StreamEventTransformer. The TakeAndRoute uses a function to determine if it should grab the event and route it to another stream, or simply forward it along.
Here's what I came up with:
import 'dart:io';
import 'dart:async';
handleWebSocket(WebSocket webSocket) {
webSocket.listen((event) {
if (event is MessageEvent) {
/* Handle message. */
} else if (event is CloseEvent) {
/* Handle closed. */
}
});
}
typedef bool ShouldTake(e);
typedef void RouteTo(Stream stream);
typedef void HandleEvent(e);
class TakeAndRoute<S, T> extends StreamEventTransformer<S, T> {
ShouldTake shouldTake;
RouteTo routeTo;
StreamController controller = new StreamController();
HandleEvent handler;
TakeAndRoute(this.shouldTake, {this.routeTo, this.handler}) {
if (routeTo != null) routeTo(controller.stream);
}
handleData(event, StreamSink sink) {
print("handling");
if (shouldTake(event)) {
if (routeTo != null) {
controller.add(event);
}
if (handler != null) {
handler(event);
}
} else {
sink.add(event);
}
}
}
main() {
HttpServer.bind('127.0.0.1', 8888)
.then((HttpServer server) {
server
.transform(new TakeAndRoute<HttpRequest, HttpRequest>(
(req) => req.uri.path == '/ws',
routeTo: (stream) => stream.transform(new WebSocketTransformer()).listen(handleWebSocket)))
.transform(new TakeAndRoute<HttpRequest, HttpRequest>(
(req) => req.uri.path == '/foo',
handler: (req) {
print('got foo');
req.response.addString("foo");
req.response.close();
}))
.listen((req) {
print("got 404 for ${req.uri}");
req.response.statusCode = 404;
req.response.close();
});
});
}
Admittedly, this might be overkill.
Here is a more manual, but shorter way to do it:
HttpServer.bind('127.0.0.1', 8889)
.then((HttpServer server) {
var sc = new StreamController();
sc.stream.transform(new WebSocketTransformer()).listen(handleWebSocket);
server.listen((HttpRequest request) {
print("new connection from ${request.uri.scheme} ${request.uri}");
// See https://code.google.com/p/dart/issues/detail?id=8825
//if (request.uri.scheme == 'ws') {
if (request.uri.path == '/ws') {
sc.add(request);
} else if (request.uri.path == '/foo') {
request.response.addString('foo');
request.response.close();
} else {
print("got 404 for ${request.uri}");
request.response.statusCode = 404;
request.response.close();
}
});
});
Notice how I had to create a StreamController so I could pump events to WebSocketTransformer

Resources