Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use WebSockets and Socket.IO with flutter?

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!

like image 624
Himanshu Ranjan Avatar asked Sep 18 '25 03:09

Himanshu Ranjan


2 Answers

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

like image 105
Aviv Lo Avatar answered Sep 19 '25 15:09

Aviv Lo


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();
}
}
like image 24
Jairo Rodriguez Avatar answered Sep 19 '25 15:09

Jairo Rodriguez