4

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!

1

2 Answers 2

8

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

11
  • What are the alternatives here? Commented Sep 29, 2020 at 13:47
  • You either use websocket or socket io. You have to choose one.
    – Algo7
    Commented Sep 29, 2020 at 14:02
  • If I choose Socket.io for node which library to use for flutter client? and similar for websocket? Commented Sep 29, 2020 at 14:03
  • Maybe have a look at this post: medium.com/@andryy.ko/…
    – Algo7
    Commented Sep 29, 2020 at 14:06
  • We don't necessarily need node.js for implementing this? Commented Sep 29, 2020 at 14:45
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();
}
}
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.