socket.io-client-dart icon indicating copy to clipboard operation
socket.io-client-dart copied to clipboard

issue with client connecting multiple times

Open mattjslaton opened this issue 4 years ago • 4 comments


import 'package:socket_io_client/socket_io_client.dart';

import '../../config.dart';
import '../showSnack.dart';

class DataStreamBloc {
  final _stateStreamController = StreamController<Map>();

  StreamSink<Map> get dataSink => _stateStreamController.sink;
  Stream<Map> get dataStream => _stateStreamController.stream;
}

StreamController<Map> controller = StreamController<Map>.broadcast();
Stream stream = controller.stream;

final dataStreamBloc = DataStreamBloc();
registerToken(context) async {
  var token = await readToken();

  if (token.isNotEmpty) {
    Socket socket = io(
'http://localhost:4400/api/ws'
       ,
        OptionBuilder()
            //  .setTransports(['websocket']) // for Flutter or Dart VM
            .enableReconnection()
            .enableAutoConnect() // disable auto-connection
            .setQuery({'token': '$token'})
            .disableForceNew()
            .disableForceNewConnection()
            .disableMultiplex()
            .setReconnectionDelay(10) // optional
            .build());
    print(socket.connected);
    if (socket.connected == false) {
      socket.connect();
    }

    socket.on('fromServer', (data) {
      print('fromServer: ' + data.toString());
    });
    socket.on('serverData', (data) {
      if (data.runtimeType.toString() == 'String') {
        var dataDecoded = jsonDecode(data.toString());
        Map dataMapped = json.decode(dataDecoded);
        var type = dataMapped['type'];
        var from = dataMapped['from'];
        var task = dataMapped['task'];

        print(dataMapped['task']);
        print(dataMapped);
        dataStreamBloc.dataSink.add(dataMapped);
        controller.add(dataMapped);
        if (type == "sessionRequest") {
          showSnack(context, 'Do you wish to accept a call from $from?');
        }
        if (type == "message") {
          showSnack(context, 'new message from $from');
        }

        return data;
      }
    });
  } else {
    print('token is missing, ask the user to log back in again');
  }
}

I am using getToken(context) within an init state to call socket.io, client seems to connect multiple times and that is what is causing a repeat of the information being received, on the server side I use the token to auth them and put them inside of a channel where I can then broadcast to that channel for any updates that the server has for a client. I am using socket.io for notifications and chat request. I know it is on the client side because on there server it only shows the broadcast function getting hit once. How do I make sure that this client only connects when there is not an active socket.io stream already connected? Thanks!

mattjslaton avatar Jun 20 '21 15:06 mattjslaton

it was the stream itself, i was subscribed to it multiple times

mattjslaton avatar Jun 21 '21 20:06 mattjslaton

Hi, I am also facing the issue of multiple client connections to the server (nodejs). On both Server as well as Client, disconnect event is called and the socket is disconnected. But as soon as a new connection is established the older connection again pops up and tries to connect to server. Hence the older ones are always there which increases by 1 every time a new Socket connection is established. I am using the version ^2.0.0-beta.2 on client side and ^4.0.2 on server side.

Options Builder configuration,

IO.OptionBuilder() .setTransports(['websocket']) .setQuery(query) .setAuth(auth) .enableForceNew() // tried without this too .disableAutoConnect() // tried without this too .build();

Disposal of socket client,

void disposeAndDestroyClient() { this.socket.dispose(); this.socket.destroy(); }

Connecting socket client,

Future<bool> _tryConnectingSocket() async { this.socket.connect(); return Future.delayed( const Duration(milliseconds: 100), () => this.socket.connected); }

On Server side for a 'disconnecting' socket,

io.of(nsp).on('disconnecting', (socket, reason) => { socket.removeAllListeners('connection') socket.offAny() socket.rooms.forEach((room) => socket.leave(room)) })

PS: I am developing a PubSub client package in dart that can be used in flutter, but for now I am testing the code on the dart vm in the tests itself, and not on an emulator or device. Does this has to do anything with the issue..? I am calling the above mentioned method "disposeAndDestroyClient()" in the tearDownAll() method of the tests which does get called successfully at the end of the test session.

Rushabh1798 avatar Jun 29 '21 04:06 Rushabh1798

I have the same issue. I fixed it used the option enableForceNewConnection on socket creation. Example:

 socket = io(EnvVar.SERVER_URL, OptionBuilder()
            .setTransports(['websocket']) // for Flutter or Dart VM
            .enableForceNewConnection() // necessary because otherwise it would reuse old connection
            .setExtraHeaders(<String, dynamic>{
              JsonKey.EMAIL: user.email,
              JsonKey.PASSWORD: user.password,
            })
            .build()

LostInDarkMath avatar Jun 29 '21 19:06 LostInDarkMath

Thanks. That solved the issue.

Rushabh1798 avatar Jun 30 '21 13:06 Rushabh1798

I have the same issue. I fixed it used the option enableForceNewConnection on socket creation. Example:

 socket = io(EnvVar.SERVER_URL, OptionBuilder()
            .setTransports(['websocket']) // for Flutter or Dart VM
            .enableForceNewConnection() // necessary because otherwise it would reuse old connection
            .setExtraHeaders(<String, dynamic>{
              JsonKey.EMAIL: user.email,
              JsonKey.PASSWORD: user.password,
            })
            .build()

Thanks, I spent my whole day to find the solution for this. Finally, it worked 😄 !!

starfreck avatar Dec 17 '23 20:12 starfreck