Bien en continuación a los temas:
Sockets Conexion,Envio y recepcion de datos (mini-chat Cliente-Servidor)
vio-y-recepcion-de-datos-mini-chat-cliente-servidor#199
[Tienes que estar registrado y conectado para ver este vínculo]Sockets Serializacion (Envio de objetos a traves de sockets)
[Tienes que estar registrado y conectado para ver este vínculo]Servidor:
[Tienes que estar registrado y conectado para ver esa imagen]Cliente:
[Tienes que estar registrado y conectado para ver esa imagen]Según sabemos el puerto es la entrada en ambos programas o computadoras, por lo tanto para poderme conectar de una computadora 'A' a una 'B' es necesario un puerto especifico en ambos lados y conectarse a el.
Debido a que por un solo puerto solo puede conectarse un cliente necesitamos que el servidor establezca que puertos tiene disponibles para conexiones entrantes.
¿Como logramos que nuestro servidor asigne los puertos?
Llevando una lista de los puertos que tenemos ocupados por conexiones "sockets" en ellos mientras guardamos las conexiones en una lista de sockets.
El programa ejemplo que proporciono ahora es un chat multisocket, es un tanto sencillo una vez entendida la lógica, veamos:
El problema radica en la explicación anterior, "un socket solo puede tener un puerto", por lo tanto debemos conectar diferentes clientes a diferentes puertos del servidor.
En este caso el ejemplo es un chat donde multiples clientes se podrán comunicar entre sí.
¿Como funciona el servidor?
Se encargará de recibir el mensaje y decidir cual será el cliente destino.
Es decir, enviará un mensaje y a su vez un identificador que nos dirá cual será el cliente destino.
¿Como funciona el cliente?
Se limita a envió de mensajes y conexiones.
1. El servidor tendrá una puerta de entrada fija por el cual todos los clientes se conectarán, en este caso será "666".
Este puerto le llamaremos entrada, ya que todos los programas cliente se conectarán al servidor a este puerto para preguntarle
Cliente: "¿Tienes algún puerto disponible?"
Servidor: "Espera dejame ver..."
2. El servidor envía un mensaje de regreso...
Servidor: "Sí tengo puertos disponibles, puedes acceder a mi puerto 250 por el cual te esperaré solo a ti"
3.El cliente recibe el mensaje que contiene el puerto al cual se conectará y lo almacena.
El servidor dice "Ya te estoy esperando en el puerto 250 ahora desocupa la entrada" (ambos programas se desconectan de la entrada).
4.El servidor empieza a escuchar en el puerto especificado por el servidor y el cliente se conecta al servidor pero esta vez al puerto recibido en el mensaje anterior.
5.Si todo ha salido bien la conexión tendrá éxito y se mantendrán las múltiples conexiones en una lista.
Ya que estoy continuando con los proyectos anteriores y temas dejaré el código completo del servidor y cliente dando por hecho que ya tienen la librería "Objeto_serial" que es el objeto que creamos en el tema anterior:
Sockets Serializacion (Envió de objetos a través de sockets)
[Tienes que estar registrado y conectado para ver este vínculo]Servidor:
- Código:
-
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using Objeto_Serializable;
namespace Ejemplo_Servidor
{
public partial class Form1 : Form
{
TcpListener servidor = new TcpListener(IPAddress.Any, 666);
List<TcpClient> Clientes_Conectados = new List<TcpClient>();
Timer tmrEscuchar = new Timer();
Timer tmrRecibir = new Timer();
Timer tmrEscuchar_Clientes = new Timer();
TcpListener _servidor=null;
public Form1()
{
InitializeComponent();
tmrEscuchar.Tick += new EventHandler(tmrEscuchar_Tick);
tmrRecibir.Tick += new EventHandler(tmrRecibir_Tick);
tmrEscuchar_Clientes.Tick += new EventHandler(tmrEscuchar_Clientes_Tick);
}
private void btnEmpezar_Click(object sender, EventArgs e)
{
servidor.Start();
tmrEscuchar.Start();
}
void tmrEscuchar_Tick(object sender, EventArgs e)
{
if (servidor.Pending()) // Determina si hay conexiones pendientes
{
TcpClient Temporal = servidor.AcceptTcpClient();
int puerto = Puertos_Manejador.Puerto_Disponible();
Objeto_Serial objeto_enviado = new Objeto_Serial();
objeto_enviado.Entero = puerto;
ER.Enviar(Temporal, objeto_enviado);
Temporal.Close();
_servidor = new TcpListener(IPAddress.Any, puerto);
_servidor.Start();
tmrEscuchar_Clientes.Start();
}
}
void tmrEscuchar_Clientes_Tick(object sender, EventArgs e)
{
if (_servidor.Pending())
{
Clientes_Conectados.Add(_servidor.AcceptTcpClient());
lbClientes.Items.Add(Clientes_Conectados.Count);
tmrRecibir.Start();
Objeto_Serial objeto_serial = new Objeto_Serial();
objeto_serial.Objeto=Clientes_Conectados.Count;
foreach (TcpClient client in Clientes_Conectados)
{
ER.Enviar(client,objeto_serial );
}
lblEstado.Text = "Conectado";
tmrEscuchar_Clientes.Stop();
_servidor.Stop();
_servidor = null;
}
}
void tmrRecibir_Tick(object sender, EventArgs e)
{
try {
foreach (TcpClient Cliente in Clientes_Conectados)
{
if (Cliente.Available > 0)//Si hay informacion disponible que leer
{
Objeto_Serial objeto_Recibido = (Objeto_Serial)ER.Recibir_Objeto(Cliente);
ER.Enviar(Clientes_Conectados[objeto_Recibido.Entero], objeto_Recibido);
}
}
}
catch (Exception)
{ }
}
}
}
Cliente:
- Código:
-
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using Objeto_Serializable;
namespace Ejemplo_Cliente
{
public partial class Form1 : Form
{
static TcpClient Cliente = new TcpClient();
Timer tmrRecibir = new Timer();
bool recibir_ip = true;
public Form1()
{
InitializeComponent();
tmrRecibir.Tick += new EventHandler(tmrRecibir_Tick);
}
void tmrRecibir_Tick(object sender, EventArgs e)
{
try
{
if (Cliente.Available > 0)//Si hay informacion disponible que leer
{
if (recibir_ip)
{
Objeto_Serial objeto_Recibido = (Objeto_Serial)ER.Recibir_Objeto(Cliente);
Cliente.Close();
Cliente = new TcpClient();
Cliente.Connect(IPAddress.Parse("127.0.0.1"), objeto_Recibido.Entero);
lblEstado.Text = "Conectado";
recibir_ip = false;
}
else
{
Objeto_Serial objeto_Recibido = (Objeto_Serial)ER.Recibir_Objeto(Cliente);
rtbConversacion.Text += "Cliente "+objeto_Recibido.Entero.ToString()+ ": " + objeto_Recibido.Cadena + "\n" ;
if (objeto_Recibido.Objeto != null)
{
lbConectados.Items.Clear();
for (int i = 0; i < (int)objeto_Recibido.Objeto; i++)
{ lbConectados.Items.Add(i); }
}
}
}
}
catch (Exception)
{ }
}
private void btnConectar_Click(object sender, EventArgs e)
{
try
{
Cliente.Connect(IPAddress.Parse("127.0.0.1"), 666);//Conectar a servidor por el puerto 666
if (Cliente.Connected)
{
tmrRecibir.Start();
}
}
catch (Exception) { lblEstado.Text = "Desconectado"; }
}
private void btnEnviar_Click(object sender, EventArgs e)
{
if (txtMensaje.Text != "")
{
if (lbConectados.SelectedIndex >= 0)
{
Objeto_Serial objeto_A_Enviar = new Objeto_Serial();
objeto_A_Enviar.Cadena = txtMensaje.Text; //El mensaje del textbox
objeto_A_Enviar.Entero = lbConectados.SelectedIndex; //Cliente
ER.Enviar(Cliente, objeto_A_Enviar);//Enviar objeto
rtbConversacion.Text += "Yo : " + objeto_A_Enviar.Cadena + "\n";
txtMensaje.Text = "";
}
}
}
}
}
Para probar los códigos, abran el programa servidor una vez empiecen a escuchar y luego abran múltiples programas cliente y conectense para ver el funcionamiento, seleccionen el amigo al con el que quieran comunicarse y listo que empiece la platica.
Servidor:
[Tienes que estar registrado y conectado para ver este vínculo]Cliente:
[Tienes que estar registrado y conectado para ver este vínculo]