ZetCode

Dart SocketMessage

last modified October 18, 2026

The SocketMessage class in Dart is a container for a message received from a socket. It holds the message data and any control messages that arrived with it.

SocketMessage is returned by RawSocket.readMessage. It's part of Dart's dart:io library. Framing and serialization are application-level concerns; the examples below build common patterns on top of SocketMessage.data.

Basic Definition

SocketMessage has two fields: data, a Uint8List containing the received bytes, and controlMessages, a list of SocketControlMessage objects.

On the receiving side, RawSocket.readMessage returns a SocketMessage? when data is available. On the sending side, use RawSocket.write for plain data, or RawSocket.sendMessage when control messages must be attached.

Basic SocketMessage Usage

This example sends a text message through a socket and reads it as a SocketMessage.

main.dart
import 'dart:io';

void main() async {
  var server = await RawServerSocket.bind('127.0.0.1', 4040);
  print('Server listening on port ${server.port}');

  server.listen((client) {
    client.listen((event) {
      if (event == RawSocketEvent.read) {
        var message = client.readMessage();
        if (message != null) {
          print('Data: ${String.fromCharCodes(message.data)}');
          print('Control messages: ${message.controlMessages.length}');
          client.close();
        }
      }
    });
  });

  var client = await RawSocket.connect('127.0.0.1', 4040);
  client.write('Hello, SocketMessage!'.codeUnits);

  await Future.delayed(Duration(seconds: 1));
  await client.close();
  await server.close();
}

We create a RawServerSocket and a RawSocket client. The client writes a UTF-8 string. The server calls readMessage to receive a SocketMessage and prints its data and control message count.

$ dart main.dart
Server listening on port 4040
Data: Hello, SocketMessage!
Control messages: 0

Handling Binary Data

This example demonstrates working with binary data in SocketMessage.

main.dart
import 'dart:io';
import 'dart:typed_data';

void main() async {
  var server = await RawServerSocket.bind('127.0.0.1', 4041);
  server.listen((client) {
    client.listen((event) {
      if (event == RawSocketEvent.read) {
        var message = client.readMessage();
        if (message != null && message.data.length >= 4) {
          var type = ByteData.sublistView(message.data, 0, 4)
              .getUint32(0);
          print('Received message type: $type');
          print('Payload: ${message.data.sublist(4)}');
          client.close();
        }
      }
    });
  });

  var client = await RawSocket.connect('127.0.0.1', 4041);
  var payload = Uint8List.fromList([1, 2, 3, 4, 5]);
  var buffer = ByteData(4 + payload.length);
  buffer.setUint32(0, 42);
  buffer.buffer.asUint8List().setAll(4, payload);

  client.write(buffer.buffer.asUint8List());
  await Future.delayed(Duration(seconds: 1));
  await client.close();
  await server.close();
}

We build a binary message with a 4-byte type header followed by a payload. The server reads a SocketMessage and extracts the type from message.data. This is efficient for binary protocols.

$ dart main.dart
Received message type: 42
Payload: [1, 2, 3, 4, 5]

Message Framing

This example shows how to implement message framing with length prefixes.

main.dart
import 'dart:io';
import 'dart:typed_data';
import 'dart:convert';

void main() async {
  var server = await RawServerSocket.bind('127.0.0.1', 4042);
  server.listen((client) {
    var buffer = <int>[];
    client.listen((event) {
      if (event == RawSocketEvent.read) {
        var message = client.readMessage();
        if (message == null) return;

        buffer.addAll(message.data);
        while (buffer.length >= 4) {
          var length = ByteData.sublistView(
              Uint8List.fromList(buffer), 0, 4).getUint32(0);
          if (buffer.length < 4 + length) break;

          var content = utf8.decode(buffer.sublist(4, 4 + length));
          print('Framed message: $content');
          buffer = buffer.sublist(4 + length);
          client.close();
        }
      }
    });
  });

  var client = await RawSocket.connect('127.0.0.1', 4042);
  var content = utf8.encode('Hello, framed world!');
  var frame = ByteData(4 + content.length);
  frame.setUint32(0, content.length);
  frame.buffer.asUint8List().setAll(4, content);

  client.write(frame.buffer.asUint8List());
  await Future.delayed(Duration(seconds: 1));
  await client.close();
  await server.close();
}

We implement length-prefixed message framing on top of SocketMessage.data. The message starts with a 4-byte length followed by the payload. The server buffers bytes until a complete frame is available, which handles message boundaries correctly.

$ dart main.dart
Framed message: Hello, framed world!

JSON Message Format

This example demonstrates using JSON for structured message content.

main.dart
import 'dart:convert';
import 'dart:io';

void main() async {
  var server = await RawServerSocket.bind('127.0.0.1', 4043);
  server.listen((client) {
    client.listen((event) {
      if (event == RawSocketEvent.read) {
        var message = client.readMessage();
        if (message != null) {
          var decoded = json.decode(utf8.decode(message.data));
          print('${decoded['type']}: ${decoded['payload']}');
          client.close();
        }
      }
    });
  });

  var client = await RawSocket.connect('127.0.0.1', 4043);
  var message = {
    'type': 'user.login',
    'payload': {'username': 'johndoe', 'password': 'secret'},
    'timestamp': DateTime.now().toIso8601String()
  };
  client.write(utf8.encode(json.encode(message)));

  await Future.delayed(Duration(seconds: 1));
  await client.close();
  await server.close();
}

We encode structured data as JSON in the bytes that become SocketMessage.data. The server decodes the JSON and extracts the message components. This is useful for web APIs and structured communication.

$ dart main.dart
user.login: {username: johndoe, password: secret}

Error Handling

This example shows robust error handling in socket message processing.

main.dart
import 'dart:convert';
import 'dart:io';

void main() async {
  var server = await RawServerSocket.bind('127.0.0.1', 4044);
  server.listen((client) {
    client.listen(
      (event) {
        if (event == RawSocketEvent.read) {
          var message = client.readMessage();
          if (message == null) return;

          try {
            var data = utf8.decode(message.data);
            var parts = data.split(':');
            if (parts.length != 2) throw FormatException('Invalid format');
            print('Command: ${parts[0]}, Args: ${parts[1].split(',')}');
            client.write(utf8.encode('ok'));
          } catch (e) {
            print('Error processing message: $e');
            client.write(utf8.encode('error:Invalid message format'));
          }
        } else if (event == RawSocketEvent.readClosed ||
            event == RawSocketEvent.closed) {
          client.close();
        }
      },
      onError: (e) => print('Connection error: $e'),
      onDone: () {
        print('Client disconnected');
        client.close();
      },
    );
  });

  var client = await RawSocket.connect('127.0.0.1', 4044);
  client.write(utf8.encode('calculate:add,5,3'));

  client.listen((event) {
    if (event == RawSocketEvent.read) {
      var response = client.read();
      if (response != null) {
        print('Server response: ${utf8.decode(response)}');
      }
    }
  });

  await Future.delayed(Duration(seconds: 1));
  await client.close();
  await server.close();
}

We read the message as a SocketMessage, validate its data, and send an error response if parsing fails. The client prints the server response and then closes the connection.

$ dart main.dart
Command: calculate, Args: [add, 5, 3]
Server response: ok
Client disconnected

Best Practices

Source

Dart SocketMessage Documentation

This tutorial covered Dart's SocketMessage patterns with practical examples showing text/binary formats, framing, JSON, and error handling for robust network communication.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Dart tutorials.