Communication Protocols and Connecting Devices
Learning Objectives
- You understand the role of communication protocols when connecting devices.
- You know of WebSockets and you can create a Flutter application that interacts with a WebSocket server.
Communication protocols
When a system that allows cross-device interaction is decomposed into parts, we can view it as connected devices that communicate in some way. The chosen communication protocol depends to some extent on the objectives; for example, the protocol might be chosen based on latency, bandwidth, security, distance between devices, required power, or desired ease of use, or a combination of these.
As an example, near-field communication (NFC) allows devices to communicate when they are close to each other (up to a few centimeters). The protocol has an initiator and a target, where the initiator can power the target device using radio frequency, allowing also communication with initially unpowered targets, such as in the case of contactless payment.
Similarly, Bluetooth allows devices to communicate wirelessly over short distances, typically up to 10 meters. The protocol is typically used to avoid the need for a wired connection, and it is used in various devices, such as headphones, speakers, and smartwatches.
In the past, bluetooth has also been used for mobile marketing, such as sending advertisements to mobile phones, but this has since been limited as mobile phone vendors have implemented measures to prevent unwanted messages.
Wi-Fi is another wireless communication protocol that allows devices to communicate over longer distances, typically up to a few hundred meters, depending on whether there are walls or other obstacles in the way. Wi-Fi is commonly used in homes, offices, and public spaces to connect devices to the internet.
When devices are not close to each other, they can communicate over the internet. This is typically done by connecting the devices to a centralized server, which then relays messages between the devices. For example, when you send a message to a friend on a messaging app, the message is typically sent to a server, which then forwards the message to your friend’s device.
There are also a range of protocols for connecting devices directly over the internet, such as WebSockets, which allows bidirectional communication channel over a single, long-lived connection. Websockets are commonly used in web applications to provide real-time communication between the client and the server.
Connecting devices over WebSocket
To connect devices over WebSocket in Flutter, we can use the library web_socket_channel
. To use it, we need to add it to the dependencies (the pubspec.yaml
file) of the project, and import it to the Dart files where it is used.
dependencies:
# new line:
web_socket_channel: 3.0.1
The library provides a WebSocketChannel class that can be used to connect to a WebSocket server. The class has a stream property that can be used to listen to messages from the server, and a sink property that can be used to send messages to the server.
An application that connects to a WebSocket server and listens to messages from the server can be implemented as follows:
final server = 'server address';
final channel = WebSocketChannel.connect(
Uri.parse(server),
);
channel.stream.listen(
(message) {
print('Received: $message');
},
);
Similarly, an application that sends a message to the server can be implemented as follows:
final server = 'server address';
final channel = WebSocketChannel.connect(
Uri.parse(server),
);
channel.sink.add('Hello, server!');
In a Flutter application, it would be sensible to create a separate class that manages the WebSocket connection, and then use the class in the widgets that need to send or receive messages. With GetX, one way would be to use an instance that inherits GetxController and initiates the connection in the onInit
method.
Such a class could be implemented, for example, as follows.
class WebSocketController extends GetxController {
WebSocketChannel? channel;
var messages = <String>[].obs;
@override
void onInit() {
super.onInit();
channel = WebSocketChannel.connect(
Uri.parse('server address'),
);
channel!.stream.listen(
(event) {
messages.add(event.toString());
},
);
}
void sendMessage(String message) {
channel!.sink.add(message);
}
@override
void onClose() {
channel!.sink.close();
super.onClose();
}
}
In the above example, a websocket connection is initiated in the onInit
method, and messages from the server are added to the messages
list. The messages
list is reactive, meaning that the components that would use the messages would be updated automatically when the list changes. The above example also demonstrates the use of onClose
, which is called when the controller is removed from memory. This is a good place to close the connection to the WebSocket server.
Example chat application
There is a simple websocket-based chat application that is available at https://dad-etc-websocket-example.deno.dev/. The application allows users to send messages to the server, which then forwards the messages to all connected clients. When used as a WebSocket server, the connection is made to wss://dad-etc-websocket-example.deno.dev/
.
The example below demonstrates a Flutter-based chat application that connects to the WebSocket server and allows users to send and receive messages. The application uses GetX for state management and for managing the WebSocket connection.
The application consists of two widgets: MessageListWidget
and MessageInputWidget
. The MessageListWidget
displays the messages received from the server, and the MessageInputWidget
allows the user to send messages to the server. The WebSocketController
class manages the WebSocket connection and the messages received from the server.
If you’re interested in building a WebSocket server, MDN Web Docs have a tutorial on Writing a WebSocket server in JavaScript (Deno), which should be straightforward to follow if you’re somewhat familiar with Web Software Development. Web Sockets are discussed in more detail in the course Designing and Building Scalable Web Applications.