How to use WebSockets and Socket.IO with flutter?

9,275

Solution 1

You can't really do that. Websocket and socket.io is different. Socket.io is written on top websocket. However, it has code written so that it's ready to fallback to other communication methods like long polling or multipart stream. In order to do that socket.io adds additional metadata to each packet. And because of that socket io client won't work with websocket server while websocket client won't work with socket io server.

The socket io doc explains why you can't do that on its first page: https://socket.io/docs/

Here is another good posts explaining the difference: https://www.hackdoor.io/articles/6xQkgQo4/differences-between-websockets-and-socketio

Solution 2

I have the socket.io server and the app with flutter

I recommend using express 4.17.1 and socket.io 2.3.0 server side

const patch=require('path');
const express=require('express');
const app=express();
const socketIO=require('socket.io');

//setting 
app.set('port', process.env.PORT || 3000);

//static file
app.use(express.static(patch.join(__dirname,'public')))
console.log(patch.join(__dirname,'public'));

//start server
const server=app.listen(app.get('port'), () => {
    console.log('servidor en el puerto ', app.get('port'));
});

//socketIO 
const io=socketIO(server);

io.on('connection', function(socket) {
    id=socket.id;
    console.log('new connection ',id);

    socket.on('carrito:all',function(data) {
        console.log("todo disp "+data);
    })

    socket.on('admin:user',function(data) {
        console.log("res login ");
    })

    socket.on('disconnect', function(){
        console.log('user '+socket.id+' disconnected ');
    });
});

https://pub.dev/packages/socket_io_client/versions/0.9.12

This will add a line like this to your package's pubspec.yaml

dependencies:
  socket_io_client: ^0.9.12

Now in your Dart code, you can use:

import 'package:socket_io_client/socket_io_client.dart' as IO;

class _MyHomePageState extends State<MyHomePage>{

IO.Socket socket;
String userid="";
@override
void initState() {

  //IO.Socket socket;
  socket = IO.io(
    'http://192.168.0.12:3000',
    <String, dynamic>{
      'transports': ['websocket']
    },
  );

  socket.onConnect((data){
     log('connect');
     userid=socket.id;
     log("id: "+userid);
     socket.on('carrito:all', (data){
       log("mensaje: "+data.toString());
     });
  });

  //socket.emit('carrito:all', {'id': userid});
  socket.on('carrito:all', (data){
    log("message "+data.toString());
  });
  socket.connect();
  super.initState();
}
}
Share:
9,275
Himanshu Ranjan
Author by

Himanshu Ranjan

Updated on December 24, 2022

Comments

  • Himanshu Ranjan
    Himanshu Ranjan over 1 year

    I have been trying to integrate my flutter app with a node js server using sockets and I am using WebSockets for the flutter part and Socket.io for the nodejs part and making a server to connect it to the flutter client.

    const express= require('express');
    const app= express();
    const http=require('http');
    const socketio= require('socket.io');
    const server= http.createServer(app);
    const io=socketio(server);
    app.get('/',(req,res)=>{
        res.send('hey people')
    })
    const PORT= process.env.PORT||3000;
    io.on('connection', (socket) => {
        console.log('a user connected');
      });
    server.listen(PORT,()=> console.log('app started'));
    

    I created a server on 3000 port here and now I want to communicate with this server using flutter client side.

    import 'package:flutter/foundation.dart';
    import 'package:web_socket_channel/io.dart';
    import 'package:flutter/material.dart';
    import 'package:web_socket_channel/web_socket_channel.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final title = 'WebSocket Demo';
        return MaterialApp(
          title: title,
          home: MyHomePage(
            title: title,
            channel: IOWebSocketChannel.connect('ws://localhost:3000'),
          ),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      final String title;
      final WebSocketChannel channel;
    
      MyHomePage({Key key, @required this.title, @required this.channel})
          : super(key: key);
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      TextEditingController _controller = TextEditingController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Form(
                  child: TextFormField(
                    controller: _controller,
                    decoration: InputDecoration(labelText: 'Send a message'),
                  ),
                ),
                StreamBuilder(
                  stream: widget.channel.stream,
                  builder: (context, snapshot) {
                    return Padding(
                      padding: const EdgeInsets.symmetric(vertical: 24.0),
                      child: Text(snapshot.hasData ? '${snapshot.data}' : ''),
                    );
                  },
                )
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _sendMessage,
            tooltip: 'Send message',
            child: Icon(Icons.send),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    
      void _sendMessage() {
        if (_controller.text.isNotEmpty) {
          widget.channel.sink.add(_controller.text);
        }
      }
    
      @override
      void dispose() {
        widget.channel.sink.close();
        super.dispose();
      }
    }
    

    After these when I am trying to send a message and get it back, I am not able to do it. I really think this should work. If not What should? Really need some help here. Thanks!

  • Himanshu Ranjan
    Himanshu Ranjan over 3 years
    What are the alternatives here?
  • Aviv Lo
    Aviv Lo over 3 years
    You either use websocket or socket io. You have to choose one.
  • Himanshu Ranjan
    Himanshu Ranjan over 3 years
    If I choose Socket.io for node which library to use for flutter client? and similar for websocket?
  • Aviv Lo
    Aviv Lo over 3 years
    Maybe have a look at this post: medium.com/@andryy.ko/…
  • Himanshu Ranjan
    Himanshu Ranjan over 3 years
    We don't necessarily need node.js for implementing this?
  • Aviv Lo
    Aviv Lo over 3 years
    Well, you can use nodejs on the backend or other languages. Websocket is not framework-specific while socket.io is less flexible and works more smoothly with javascript. You can do PHP / C# and any web languages with WebSocket as well.
  • Himanshu Ranjan
    Himanshu Ranjan over 3 years
    So,the backend I make here should use Socket.io right?
  • Aviv Lo
    Aviv Lo over 3 years
    Yes. Because you're using javascript.
  • Himanshu Ranjan
    Himanshu Ranjan over 3 years
    I implmented the solution you proposed. Didn't get the output tho.Can you check it here?github.com/Himanshuranjan30/Socket-Flutter-Chat
  • Aviv Lo
    Aviv Lo over 3 years
    Ok. Perhaps open the other question for this and link me there. I'll answer it over there.
  • Himanshu Ranjan
    Himanshu Ranjan over 3 years
    stackoverflow.com/questions/64156395/… Here's the link to that question