En esta lección crearemos un cliente que establecerá conexión con el servidor.
Usando el código del servidor de la lección anterior (TcpListener) y el cliente de esta sección (TcpClient), implementaremos paso a paso una herramienta de chat TCP.
Diferencias de conceptos
- Servidor: TcpListener
Se enlaza a una IP fija y al puerto fijo 9500. Se mantiene escuchando de forma pasiva esperando clientes, puede aceptar varias conexiones al mismo tiempo. Es como un vendedor que espera a que lleguen los compradores. - Cliente: TcpClient
No hace falta asignar un puerto manualmente. El sistema operativo asigna automáticamente un puerto temporal aleatorio para iniciar la conexión hacia el puerto 9500 del servidor.
Los puertos de los dos extremos no coinciden
Puerto aleatorio del cliente — puerto fijo del servidor 9500
Cliente de consola
using System;
using System.Net.Sockets;
namespace TalkClient
{
class Program
{
static void Main(string[] args)
{
// Creamos el objeto cliente TCP
TcpClient tcpClient = new TcpClient();
// Iniciamos conexión con el servidor local 127.0.0.1:9500
// Si usas otro equipo, escribe su IP; servidor y cliente no tienen que estar en el mismo ordenador
tcpClient.Connect("127.0.0.1", 9500);
// LocalEndPoint: dirección y puerto locales del cliente
// RemoteEndPoint: dirección y puerto del servidor remoto
Console.WriteLine("Conexión establecida, puerto local {0}, puerto servidor {1}",
tcpClient.Client.LocalEndPoint,
tcpClient.Client.RemoteEndPoint);
Console.ReadLine();
tcpClient.Close();
}
}
}Lenguaje del código: JavaScript (javascript)
Código del cliente WinForms
Controles de interfaz:
textBoxIP: IP del servidortextBoxPort: Puerto del servidorbuttonStart: Botón de conexióntextBoxInfo: Caja para mostrar mensajestextBoxMsg: Campo para escribir mensajes a enviarbuttonSend: Botón de envío
using System;
using System.Net.Sockets;
using System.Windows.Forms;
namespace SocketChatClient
{
public partial class Form1 : Form
{
TcpClient tcpClient;
public Form1()
{
InitializeComponent();
}
// Evento al pulsar el botón conectar
private void buttonStart_Click(object sender, EventArgs e)
{
tcpClient = new TcpClient();
try
{
string ip = textBoxIP.Text;
int port = Convert.ToInt32(textBoxPort.Text);
tcpClient.Connect(ip, port);
textBoxInfo.AppendText($"Conexión exitosa! Punto final local: {tcpClient.Client.LocalEndPoint}\r\n");
}
catch (Exception ex)
{
MessageBox.Show("Fallo de conexión‑" + ex.Message);
}
}
}
}Lenguaje del código: PHP (php)
Funcionamiento conjunto servidor + cliente
- Ejecuta primero el programa servidor, pulsa iniciar, llama a
TcpListener.Start()para empezar a escuchar el puerto 9500 - Luego ejecuta el programa cliente, pulsa conectar;
TcpClient.Connect()realiza el handshake de tres vías TCP - Una vez conectados, el intercambio bidireccional de mensajes se hace mediante
NetworkStream(tema del siguiente capítulo)
Observaciones
- Causas frecuentes de fallo de conexión
- Orden incorrecto: no se inició el servidor primero
- La IP o el puerto introducidos no coinciden
- Bloqueo por cortafuegos; al depurar entre varios equipos no uses
127.0.0.1, usa la IP de red local
- Conceptos sobre puertos
- El servidor mantiene el puerto 9500 fijo y puede atender varios clientes al mismo tiempo
- El puerto del cliente lo asigna aleatoriamente el sistema operativo, cambia en cada ejecución, no hay que indicarlo manualmente
- Aviso sobre bloqueos
Llamar directamente a.Connect()en aplicaciones de formulario bloquea el hilo de interfaz. En proyectos reales usa el método asíncronoConnectAsyncpara evitar que la ventana se quede colgada.
Repaso: Servidor WinForms (lección anterior)
using System;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
namespace SocketChatServer
{
public partial class Form1 : Form
{
IPAddress ip;
TcpListener listener;
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
ip = IPAddress.Parse(textBoxIP.Text);
int port = Convert.ToInt32(textBoxPort.Text);
listener = new TcpListener(ip, port);
listener.Start();
textBoxInfo.Text = $"Servidor iniciado {DateTime.Now.ToShortTimeString()}\r\n" + textBoxInfo.Text;
}
}
}Lenguaje del código: C# (cs)
Cliente