Flutter com Sockets
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.