How you can use WebSockets with Flutter

How you can use WebSockets with Flutter

WebSockets are clearly taking the industry by storm. With Google's Flutter framework on the rise too, it would give you a big boost knowing how to integrate both of these technologies.

What are WebSockets

image

WebSockets represent a long-awaited evolution in the client/server web technology. It defines a fully duplex bi-directional communication channel between the client and server.

Related: What do you mean by client and a server?

In simple words, once after the initial handshake where the server and the client agree to upgrade to WebSockets, (from HTTP) the client and the server can talk in real time without having to continuously make requests (like loading the page again and again).

Only the client-side problems of developing a dependable WebSocket-based solution for realtime Flutter apps are discussed in this article. On the server side, you must determine which solution you wish to utilise. You can use an open-source library like Socket.IO if you haven't already.

How to connect to a WebSocket server with Flutter

web_socket_channel package

We will use this package to acquire the tools we need to connect to a WebSocket server. image

  • The web_socket_channel basically works with the StreamChannel class, which is an abstract class representing a two-way communication channel (as in the case for WebSockets)
  • Each StreamChannel exposes a Stream for receiving data. A Stream is like a pipe, you put a value on the one end and if there’s a listener on the other end that listener will receive that value.
  • It also exposes StreamSink used to push messages to the server.

In short words, the package allows you to both listen for messages from the server and push messages to the server i.e fully duplex bi-directional communication channel.

Installation

Follow the installation given here: pub.dev/packages/web_socket_channel/install

Basic Idea

image

  • We'd have a textfield in our app where the user could type a message. The data that we input would be displayed on the screen after pressing a button.

  • The data displayed comes from the server response, which is an echo server in this case, meaning it sends back what it receives. These servers are used to determine whether or not a connection to a server is successful. Here we would be using them to maintain simplicity for this example.

Here is the boiler plate we will be using:

How to connect to server

First let us connect to a WebSocket server. As discussed above we will be using an echo webSocket server.

WebSocketChannel channel = IOWebSocketChannel.connect("wss://ws.ifelse.io/");
  • WebSocketChannel: A StreamChannel (class representing a two-way communication) that communicates over a WebSocket.
  • IOWebSocketChannel: A WebSocketChannel that communicates using a dart:io WebSocket.
  • IOWebSocketChannel.connect: Creates a new WebSocket connection and connects to url using WebSocket.connect and returns a channel that can be used to communicate over the resulting socket.
  • Here wss://ws.ifelse.io/ is an echo WebSocket server. Please note that the mostly used echo server ws://echo.websocket.org is no longer in service.

How to listen to the server

image

  • Now that we’ve established a connection, let us listen to messages from the server.
  • After sending a message to the test server, it sends the same message back (echo).
  • We will use a StreamBuilder widget to listen for new messages, and a Text widget to display them.
  • A StreamBuilder:
    1. Can listen to exposed streams.
    2. Return widgets
    3. Catch snapshots of got stream information.
StreamBuilder(  
  stream: widget.channel.stream,  
  builder: (context, snapshot) {  
    return Padding(  
      padding: const EdgeInsets.all(20.0),  
  child: Text(snapshot.hasData ? '${snapshot.data}' : ''),  
  );  
  },  
)

Watch this video to get a better idea about StreamBuilder:

How to Send data to the server

image

We will add a function sendData() responsible for sending data to the stream whenever the floating button is pressed.

void sendData() {  
  if (_controller.text.isNotEmpty) {  
    widget.channel.sink.add(_controller.text);  
  }  
}
  • channel.sink.add(): for sending values to the other endpoint of the stream (i.e the server) using the sink property of the WebSocketChannel.
  • To make sure we are printing not empty data we add a

How to close the connection?

Using the close method we can disconnect from the server.

void dispose() {  
  widget.channel.sink.close();  
 super.dispose();  
}

Final Code

If you successfully connected to the server then you would see this on the emulator. image

This is how your app should would look at the end: Animation

Where can you use it?

The realtime web existed before WebSockets, but it was difficult to accomplish, often slower, and based on hacking web technologies that weren't built for realtime applications. The WebSocket protocol paved the path for a genuinely real-time web and expanded the possibilities of Internet communication.

USE CASES:

  • Web-based games
  • Chatting Applications