Envío continuo desde el cliente

A continuación modificamos el código del lado del servidor de la sección anterior, para que reciba mensajes enviados por el cliente de forma continua y activamos el soporte multihilo.

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TcpServerDemo
{
    public partial class Form1 : Form
    {
        private TcpListener listener;
        private TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            Thread acceptThread = new Thread(() =>
            {
                IPAddress ip = IPAddress.Parse(this.textBoxIP.Text);//crear instancia IP
                listener = new TcpListener(ip, Convert.ToInt32(this.textBoxPort.Text));//crear objeto de escucha TCP
                listener.Start();
                this.textBoxInfo.Text = "Servidor iniciado‑" + DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;
                tcpClient = listener.AcceptTcpClient();//llamada bloqueante, esperar conexión
                this.textBoxInfo.Text = "Conexión establecida‑" + DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;

                NetworkStream stream = tcpClient.GetStream();
                byte[] byteArray = new byte[1024];
                while (true)
                {
                    int length = stream.Read(byteArray, 0, 1024);//copia los bytes del flujo al búfer byteArray
                    //length devuelve la cantidad real de bytes enviados por el cliente
                    string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);
                    this.textBoxInfo.Text = "Recibido:" + receiveMessage + "-" +
                        DateTime.Now.ToShortTimeString() + "\r\n" + this.textBoxInfo.Text;
                }
            });
            acceptThread.IsBackground = true;
            acceptThread.Start();
        }
    }
}Lenguaje del código: C# (cs)

Implementación basada en WinForms + TcpClient / TcpListener:
El cliente envía textos personalizados de forma continua al servidor; escribe 【Salir】para cerrar conexión y finalizar el programa

Este ejemplo soluciona los bloqueos de interfaz por multihilos con un método sencillo, pero la forma correcta es la siguiente:
Control.CheckForIllegalCrossThreadCalls = false; es una solución bruta no recomendada. En proyectos reales usa Invoke/BeginInvoke para actualizar controles desde hilos secundarios.

1. Lado del servidor

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace TcpServerDemo
{
    public partial class Form1 : Form
    {
        private TcpListener listener;
        private TcpClient tcpClient;

        public Form1()
        {
            InitializeComponent();
            // No usar en proyectos de producción, solo para aprendizaje
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            // Nuevo hilo para evitar bloqueos de la interfaz
            new Thread(() =>
            {
                IPAddress ip = IPAddress.Parse(textBoxIP.Text);
                listener = new TcpListener(ip, Convert.ToInt32(textBoxPort.Text));
                listener.Start();
                AppendLog($"Servidor iniciado‑{DateTime.Now.ToShortTimeString()}");

                tcpClient = listener.AcceptTcpClient();
                AppendLog($"Cliente conectado‑{DateTime.Now.ToShortTimeString()}");

                NetworkStream stream = tcpClient.GetStream();
                byte[] byteArray = new byte[1024];
                while (true)
                {
                    int length = stream.Read(byteArray, 0, 1024);
                    if (length <= 0)
                    {
                        AppendLog("El cliente cerró la conexión");
                        break;
                    }
                    string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);
                    AppendLog($"Recibido:{receiveMessage}{DateTime.Now.ToShortTimeString()}");
                }
                tcpClient.Close();
                listener.Stop();
            }).Start();
        }

        // Agregar registro al cuadro de texto
        private void AppendLog(string msg)
        {
            textBoxInfo.Text = msg + "\r\n" + textBoxInfo.Text;
        }
    }
}Lenguaje del código: C# (cs)

2. Código del cliente

Implementa entrada continua; al escribir “Salir” finaliza la comunicación

Controles sugeridos para la interfaz del cliente:

  • textBoxServerIp:IP del servidor
  • textBoxPort:Número de puerto
  • textBoxSend:Campo para escribir mensajes a enviar
  • btnConnect:Botón de conexión
  • btnSend:Botón de envío
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TcpClientDemo
{
    public partial class ClientForm : Form
    {
        private TcpClient client;
        private NetworkStream stream;
        private bool isConnected = false;

        public ClientForm()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        // Conectar con el servidor
        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                client = new TcpClient();
                client.Connect(textBoxServerIp.Text, Convert.ToInt32(textBoxPort.Text));
                stream = client.GetStream();
                isConnected = true;
                MessageBox.Show("Conexión exitosa, ya puedes enviar mensajes!");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fallo de conexión:" + ex.Message);
            }
        }

        // Lógica principal para enviar mensajes
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (!isConnected)
            {
                MessageBox.Show("Primero conéctate al servidor!");
                return;
            }
            string content = textBoxSend.Text.Trim();
            if (string.IsNullOrEmpty(content))
                return;

            // Detectar comando para salir
            if (content == "Salir")
            {
                byte[] exitData = Encoding.Unicode.GetBytes(content);
                stream.Write(exitData, 0, exitData.Length);

                // Liberar recursos
                stream.Close();
                client.Close();
                isConnected = false;
                MessageBox.Show("Conexión finalizada");
                return;
            }

            // Enviar contenido personalizado
            byte[] data = Encoding.Unicode.GetBytes(content);
            stream.Write(data, 0, data.Length);
            textBoxSend.Clear();
        }
    }
}Lenguaje del código: C# (cs)
static void Main(string[] args)
{
    TcpClient client = new TcpClient();
    client.Connect("127.0.0.1", 8899);
    NetworkStream stream = client.GetStream();
    while (true)
    {
        Console.Write("Escribe el contenido a enviar:");
        string msg = Console.ReadLine();
        byte[] buf = Encoding.Unicode.GetBytes(msg);
        stream.Write(buf,0,buf.Length);
        if (msg == "Salir")
        {
            stream.Close();
            client.Close();
            break;
        }
    }
}Lenguaje del código: JavaScript (javascript)

Si lo necesitas, puedo reescribir todo el código con sintaxis async/await totalmente asincrónica, eliminando por completo hilos auxiliares y la mala práctica de desactivar la comprobación entre hilos.

Envío continuo desde el cliente

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *