Flutter com Sockets

Tempo de leitura: 3 minutes

O Web Socket é uma tecnologia avançada usada para criar uma conexão entre um cliente e um servidor e para ser uma ponte de comunicação em tempo real entre eles.
Ele é usado constantemente em muitas áreas, como jogos on-line, aplicativos de bate-papo e aplicativos de IoT.

O Socket.io é uma biblioteca criada com base nos recursos de soquete da Web, mas oferece mais recursos aos usuários.

Basicamente, o socket.io é uma estrutura de sala em que os usuários podem se comunicar por meio de um canal.

Como resultado, o soquete da Web e o socket.io são uma estrutura ideal que facilita a comunicação em tempo real em aplicativos da Web e fornece fluxo de dados instantâneo entre os clientes e o servidor

 

Lado do cliente

No lado do aplicativo móvel, primeiro adicionamos nossas bibliotecas socket_io_client e web_socket_channel ao nosso arquivo pubspec.yaml.

dependencies:
  flutter:
    sdk: flutter

  socket_io_client:
  web_socket_channel:

 

Soquete da Web clássico

Primeiro, vamos começar com o soquete da Web clássico e criar uma variável de canal. Forneceremos todas as conexões e comunicações por meio dessa variável. Em seguida, vamos criar um botão Connect e fazer a conexão por meio desse botão.

WebSocketChannel? channel;
IconButton(
 onPressed: (){
  setState(() {
    channel = WebSocketChannel.connect(Uri.parse('ws://192.168.100.98:8080'));
  });
 }, 
 icon: Icon(FontAwesomeIcons.plug,color:Colors.green),
),

Para a estrutura de escuta, podemos capturar mensagens escutando o fluxo no canal com o StreamBuilder no canal ao qual criamos uma conexão.

StreamBuilder(
    stream: channel!.stream,
    builder: (context, snapshot) {
      if(snapshot.data != null)
      {
        print(snapshot.data);
        buffer.add(Message(snapshot.data,0));
      }

      return
         Expanded(
          child: Container(
            color: Colors.grey.shade200,
            child: ListView.builder(
              itemCount: buffer.length,
              itemBuilder: (context,index)
              {
                return BubbleSpecialThree(
                  color: buffer[index].sender==1?Colors.white70:Colors.lightBlueAccent,
                  text: buffer[index].text!,
                  isSender: buffer[index].sender==1?true:false,
                  textStyle: TextStyle(color: Colors.black),
                );
              },
            ),
          ),
        );

    }
),

Também usei a biblioteca chat_bubbles para criar recursos visuais.

Ao enviar mensagens via soquete da Web, usamos a função sink.add(“value”) no canal que criamos.

TextField(
  controller: controller,
  decoration: InputDecoration(
      suffixIcon: InkWell(
        onTap: ()async{
          String text = controller.text;

          channel!.sink.add(text);
          setState(() {
            buffer.add(Message(text,1));
            controller.text = "";
          });


        },
        child: Icon(Icons.send),
      )
  ),
)

Para fechar a conexão no canal, usamos novamente a função sink.close().

channel!.sink.close();

 

Socket.Io

Primeiro, adicionamos nossa biblioteca.

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

Em seguida, definimos a variável de soquete.

IO.Socket socket = IO.io('ws://192.168.100.71:7000/',IO.OptionBuilder().setTransports(['websocket']).build(),);

Vamos adicionar nossa classe StreamSocket, que usaremos para enviar dados via soquete e receber dados de entrada via fluxo.

class StreamSocket{
  final _socketResponse= StreamController<String>();

  void Function(String) get addResponse => _socketResponse.sink.add;

  Stream<String> get getResponse => _socketResponse.stream;

  void dispose(){
    _socketResponse.close();
  }
}

Vamos chamar nossa variável da classe StreamSocket.

StreamSocket streamSocket =StreamSocket();

Em initState, chamamos nossas funções de estado que ouviremos, como o status de erro e o status de conexão do nosso soquete.

socket.onError((data) => print("Error --> $data"));
socket.onConnecting((data) => print("Connecting --> $data"));
socket.onConnectError((data) => print("Connect Error  --> $data"));
socket.onConnect((data) => print("Connect --> $data"));

O Socket.io funciona com lógica de canal. Para ouvir os dados provenientes do lado do servidor e enviar dados, precisamos nos conectar ao canal relevante.

Abrimos nosso canal de escuta em InitState. Acionamos a função addResponse de nossa variável streamSocket sempre que chegam dados.

socket.on("tm:tasks", (data){
  streamSocket.addResponse;
  setState(() {
    buffer.add(Message("TM --> $data",0));
  });
});

Por fim, abrimos nosso soquete e estabelecemos uma conexão.

socket.open();
socket.connect();

Agora, vamos editar o canal de fluxo que vem com o streamsocket.getresponse com o streambuilder e transferi-lo para o usuário.

StreamBuilder(stream: streamSocket.getResponse, builder: (context,snapshot){
  return Expanded(
    child: Container(
      color: Colors.grey.shade200,
      child: ListView.builder(
        itemCount: buffer.length,
        itemBuilder: (context,index)
        {
          return BubbleSpecialThree(
            color: buffer[index].sender==1?Colors.white70:Colors.lightBlueAccent,
            text: buffer[index].text!,
            isSender: buffer[index].sender==1?true:false,
            textStyle: TextStyle(color: Colors.black),
          );
        },
      ),
    ),
  );
}),

Vamos adicionar nossas operações de envio de dados que usaremos no TextField. Da mesma forma, emitimos os dados que enviaremos para o canal relevante do soquete.

onTap: ()async{
  String text = controller1.text;

  socket.emit("ch:chat",controller1.text);
  setState(() {
    buffer.add(Message("TM --> "+text,1));
    controller1.text = "";
  });
},

Por fim, chamamos a função de desconexão do soquete para encerrar a conexão.

socket.disconnect();

Para o lado do servidor Web Socket Classic, usei os programas que encontrei na Microsoft Store e funcionou. Para o Socket.Io, configurei um servidor socket.io simples via node.js, mas não senti a necessidade de compartilhá-lo porque era muito curto.

Especialmente o Socket.Io me permite realizar meu trabalho de comunicação rapidamente graças aos canais de comunicação que uso muitas vezes em meus aplicativos.