Sockets en Dart

Implementa comunicación de red en tiempo real para tus aplicaciones

Descargar Ejemplos Completos

¿Qué son los Sockets?

Los sockets son endpoints de comunicación que permiten a diferentes procesos intercambiar datos, ya sea en la misma máquina o a través de una red. En Dart, la comunicación mediante sockets es fundamental para aplicaciones cliente-servidor, chat en tiempo real, juegos multijugador y más.

Comunicación Bidireccional

Cliente y servidor pueden enviar y recibir datos simultáneamente

Tiempo Real

Comunicación instantánea sin necesidad de refrescar

Arquitectura Cliente/Servidor

Múltiples clientes pueden conectarse a un mismo servidor

Arquitectura de Sockets

Cliente

Servidor

Solicitud del cliente
Respuesta del servidor

Importaciones necesarias:

import 'dart:io';      // Para sockets TCP
import 'dart:convert';  // Para codificación/decodificación

Creando un Servidor de Sockets

1. Importar dependencias

Importamos las bibliotecas necesarias para manejar sockets y entrada/salida.

2. Vincular el servidor

Especificamos la dirección IP y puerto donde el servidor escuchará conexiones.

3. Manejar conexiones

Escuchamos conexiones entrantes y manejamos los datos recibidos.

4. Manejar múltiples clientes

Mantenemos una lista de clientes conectados para broadcast.

Servidor Completo:

import 'dart:io';

void main() async {
  // Paso 2: Vincular servidor al puerto 3456
  final server = await ServerSocket.bind(
    InternetAddress.loopbackIPv4, // 127.0.0.1
    3456
  );
  
  List clientes = [];
  
  print('Servidor iniciado en ${server.address.address}:${server.port}');

  // Paso 3: Escuchar conexiones entrantes
  server.listen((Socket cliente) {
    print("Cliente conectado desde ${cliente.remoteAddress.address}");
    
    // Enviar mensaje de bienvenida
    cliente.write("¡Bienvenido a este servidor! \n");
    
    // Paso 4: Añadir cliente a la lista
    clientes.add(cliente);
    
    // Escuchar mensajes del cliente
    cliente.listen(
      (List data) {
        String mensaje = String.fromCharCodes(data).trim();
        print('Mensaje recibido: ${mensaje}');
        
        // Responder al cliente
        cliente.write("Mensaje recibido \n");
        
        // Broadcast a otros clientes
        for (var user in clientes) {
          if (user != cliente) {
            user.write("Cliente dice: $mensaje \n");
          }
        }
        
        // Comando especial 'info'
        if (mensaje == "info") {
          cliente.write("Clientes conectados: ${clientes.length} \n");
        }
      },
      
      onDone: () {
        print('Cliente desconectado');
        clientes.remove(cliente);
      },
      
      onError: (error) {
        print("Error: ${error}");
        clientes.remove(cliente);
      },
    );
  });
}

Creando un Cliente de Sockets

1. Conectar al servidor

Establecemos conexión con el servidor usando dirección IP y puerto.

2. Configurar listeners

Preparamos handlers para recibir datos del servidor.

3. Leer entrada del usuario

Capturamos entrada desde consola para enviar al servidor.

4. Manejar desconexión

Implementamos lógica para cerrar conexión limpiamente.

Cliente Completo:

import 'dart:io';
import 'dart:convert';

void main() async {
  // Paso 1: Conectar al servidor
  final socket = await Socket.connect('127.0.0.1', 3456);
  
  print("Conectado al servidor");
  socket.write("Cliente conectado");

  // Paso 2: Escuchar respuestas del servidor
  socket.listen(
    (List data) {
      String mensaje = String.fromCharCodes(data).trim();
      print("Servidor: ${mensaje}");
    },
    
    onDone: () {
      print('Conexión perdida con el servidor');
      exit(0);
    },
    
    onError: (error) {
      print("Error: ${error}");
    },
  );

  // Paso 3: Leer entrada del usuario
  stdin.transform(utf8.decoder).listen((String texto) {
    texto = texto.trim();
    
    // Paso 4: Manejar comando 'exit'
    if (texto == 'exit') {
      print('Desconectando...');
      socket.write('Cliente cerró la conexión');
      socket.close();
      exit(0);
    } else if (texto.isNotEmpty) {
      // Enviar mensaje al servidor
      socket.write(texto);
    }
  });
}

Simulador de Chat con Sockets

Offline
0
Simulación de Sockets
×
[12:00:00] SERVIDOR: Servidor iniciado en 127.0.0.1:3456
[12:00:05] SISTEMA: Usa 'info' para ver clientes conectados
$

Clientes Conectados

Propiedades y Métodos Clave

ServerSocket.bind()

Crea y vincula un servidor socket a una dirección y puerto

InternetAddress int port Future

Socket.connect()

Conecta un cliente a un servidor socket

String host int port Future

.listen()

Escucha datos entrantes en el socket

Function callback onDone onError

.write()

Envía datos a través del socket

String data List data

.close()

Cierra la conexión del socket

void

.remoteAddress

Dirección del cliente conectado

InternetAddress

Casos de Uso Comunes

💬 Chat en Tiempo Real

Aplicaciones de mensajería instantánea con múltiples usuarios conectados.

🎮 Juegos Multijugador

Sincronización de estado entre jugadores en tiempo real.

📊 Monitoreo en Tiempo Real

Sistemas de dashboard que muestran datos actualizados al instante.

🤖 Comunicación entre Microservicios

Intercambio de datos entre diferentes componentes de un sistema distribuido.

Mejores Prácticas

🔒 Manejo de Errores

Siempre implementa onError y onDone para manejar desconexiones inesperadas.

💾 Limpieza de Recursos

Remueve clientes desconectados de la lista para evitar memory leaks.

📨 Codificación de Datos

Usa utf8.decoder/encoder para manejar correctamente caracteres especiales.

⚡ Async/Await

Utiliza programación asíncrona para no bloquear el hilo principal.

Ejercicios para Practicar

Ejercicio 1: Chat Básico

Modifica el servidor para que envíe el nombre del cliente que envía cada mensaje a todos los demás.

Pista: Almacena nombres junto con los sockets y añade el nombre al mensaje de broadcast

Ejercicio 2: Comandos Especiales

Añade comandos como "/users" para listar usuarios y "/pm [usuario]" para mensajes privados.

Pista: Revisa si el mensaje comienza con "/" y procesa como comando

Ejercicio 3: Servidor con Autenticación

Implementa un sistema donde los clientes deben autenticarse con usuario/contraseña antes de chatear.

Pista: Al conectar, solicita credenciales antes de añadir a la lista general

Recursos Adicionales

Documentación Oficial

API de dart:io

Ejemplos Avanzados

GitHub Dart Samples

Tutoriales en Video

YouTube Tutorials