¿Cómo puede volver a conectar al cliente de nuevo

Estoy usando el siguiente ejemplo para recibir mensajes XML. El cliente conecta, envía un mensaje y luego cierra la conexión. Sin embargo, el oyente sólo responde a la primera conexión. Si el cliente vuelve a conectarse después del cierre, no pasa nada. Por lo tanto, el oyente debe reconocer cuando un cliente vuelve a conectarse a través del mismo puerto. He intentado bastante, pero no tengo el resultado deseado.

¿Alguien ve una solución a este ejemplo?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Xml;
using System.Xml.Linq;

namespace Socket_Server_Form
{
    public partial class Socket_Server : Form
    {
        private Thread n_server;        
        private Thread n_send_server;
        private TcpClient client;
        private TcpListener listener;
        private int port = 708;
        private string IP = "";
        private Socket socket;
        byte[] bufferReceive = new byte[4096];
        byte[] bufferSend = new byte[4096];        

        public Socket_Server()
        {
            InitializeComponent();
        }
    
        public void Server()
        {
            listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            try
            {
                socket = listener.AcceptSocket();
                if (socket.Connected)
                {
                    txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = "Client: " + socket.RemoteEndPoint.ToString(); });
                }
                while (true)
                {
                    int length = socket.Receive(bufferReceive);
                    if (length > 0)
                    {
                        txtMessages.Invoke((MethodInvoker)delegate { txtMessages.Text = Encoding.UTF8.GetString(bufferReceive); });
                    }
                }
            }
            catch (Exception ex)
            {
                txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = ("Error : " + ex.Message); });
            } 
            finally
            {
                listener.Stop();
                n_server = new Thread(new ThreadStart(Server));
                n_server.IsBackground = true;
                n_server.Abort();

                txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = ("Receiver stopped"); });

                if (socket != null)
                {                    
                    n_server = new Thread(new ThreadStart(Server));
                    n_server.IsBackground = true;
                    n_server.Start();

                    txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = ("Receiver started, waitig for next connection..."); });
                }
            }
        }

        private void send()
        {
            if (socket != null)
            {
                bufferSend = Encoding.UTF8.GetBytes(TxtSend.Text);
                socket.Send(bufferSend);
            }
            else
            {
                if (client.Connected)
                {
                    bufferSend = Encoding.UTF8.GetBytes(txtMessages.Text);
                    NetworkStream nts = client.GetStream();
                    if (nts.CanWrite)
                    {
                        nts.Write(bufferSend, 0, bufferSend.Length);
                    }
                }
            }
        }

        private void BtnStart_Click(object sender, EventArgs e)
        {
            n_server = new Thread(new ThreadStart(Server));
            n_server.IsBackground = true;
            n_server.Start();
            txtStatus.Text = "Receiver started";
        }

        private void BtnStop_Click(object sender, EventArgs e)
        {
            n_server = new Thread(new ThreadStart(Server));
            n_server.IsBackground = true;
            n_server.Abort();
            txtStatus.Text = ("Receiver stopped");
        }        

        private void BtnSend_Click(object sender, EventArgs e)
        {
            n_send_server = new Thread(new ThreadStart(send));
            n_send_server.IsBackground = true;
            n_send_server.Start();
        }        
    }
}

Pregunta hecha hace 3 años, 5 meses, 5 días - Por debugdynamo46a0


2 Respuestas:

  • Para permitir que el servidor vuelva a aceptar conexiones de clientes después de que se ha cerrado la conexión con un cliente, necesitas hacer algunos cambios en tu código. Aquí tienes algunas sugerencias:

    • Modificar el bucle while para aceptar múltiples conexiones: En lugar de tener un bucle while que espera por siempre en la misma conexión, debes modificar tu código para que el servidor pueda aceptar múltiples conexiones de manera consecutiva. Puedes hacer esto creando un nuevo hilo o tarea para manejar cada conexión individualmente.
    • Eliminar el cierre del oyente en el bloque finally: Elimina el cierre del oyente en el bloque `finally` ya que no queremos cerrar el oyente cada vez que se cierra una conexión con un cliente. En vez de eso, dejaremos el oyente abierto para aceptar nuevas conexiones.
    • Crear un nuevo hilo o tarea para manejar cada conexión: Después de aceptar una conexión, inicia un nuevo hilo o tarea para manejar esa conexión específica. Esto permitirá que el servidor siga escuchando en espera de nuevas conexiones mientras maneja activamente las conexiones existentes.

    Aquí te dejo un ejemplo de cómo podrías modificar tu método Server para implementar estas sugerencias:

    csharp
    public void Server()
    {
        listener = new TcpListener(IPAddress.Any, port);
        listener.Start();
    
        try
        {
            while (true)
            {
                socket = listener.AcceptSocket();
                if (socket.Connected)
                {
                    txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = "Client: " + socket.RemoteEndPoint.ToString(); });
                }
    
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
                clientThread.IsBackground = true;
                clientThread.Start(socket);
            }
        }
        catch (Exception ex)
        {
            txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = "Error: " + ex.Message; });
        }
    }
    
    private void HandleClient(object obj)
    {
        Socket clientSocket = (Socket)obj;
    
        try
        {
            while (true)
            {
                int length = clientSocket.Receive(bufferReceive);
                if (length > 0)
                {
                    txtMessages.Invoke((MethodInvoker)delegate { txtMessages.Text = Encoding.UTF8.GetString(bufferReceive); });
                }
            }
        }
        catch (Exception ex)
        {
            txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = "Error: " + ex.Message; });
        }
        finally
        {
            clientSocket.Close();
        }
    }
    

    Con estos cambios, tu servidor debería ser capaz de volver a conectar y manejar múltiples conexiones de clientes de manera concurrente. Recuerda ajustar cualquier otra parte del código que pueda verse afectada por estos cambios.

    Respondida el Dec 18, 2020 a las 09:37 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema con tu código es que una vez que se cierra la conexión con un cliente, el servidor cierra el socket y el hilo del servidor. Para manejar múltiples conexiones recurrentes, debes mantener el socket abierto y en espera de nuevas conexiones.

    Aquí tienes el código modificado:

    csharp
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace Socket_Server_Form
    {
        public partial class Socket_Server : Form
        {
            private Thread n_server;        
            private Thread n_send_server;
            private TcpClient client;
            private TcpListener listener;
            private int port = 708;
            private string IP = "";
            private Socket socket;
            byte[] bufferReceive = new byte[4096];
            byte[] bufferSend = new byte[4096];        
    
            public Socket_Server()
            {
                InitializeComponent();
            }
    
            public void Server()
            {
                listener = new TcpListener(IPAddress.Any, port);
                listener.Start();
                while (true)
                {
                    try
                    {
                        socket = listener.AcceptSocket();
                        if (socket.Connected)
                        {
                            txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = "Client: " + socket.RemoteEndPoint.ToString(); });
                        }
                        while (true)
                        {
                            int length = socket.Receive(bufferReceive);
                            if (length > 0)
                            {
                                txtMessages.Invoke((MethodInvoker)delegate { txtMessages.Text = Encoding.UTF8.GetString(bufferReceive); });
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = ("Error : " + ex.Message); });
                    } 
                }
            }
    
            private void send()
            {
                if (socket != null)
                {
                    bufferSend = Encoding.UTF8.GetBytes(TxtSend.Text);
                    socket.Send(bufferSend);
                }
                else
                {
                    if (client.Connected)
                    {
                        bufferSend = Encoding.UTF8.GetBytes(txtMessages.Text);
                        NetworkStream nts = client.GetStream();
                        if (nts.CanWrite)
                        {
                            nts.Write(bufferSend, 0, bufferSend.Length);
                        }
                    }
                }
            }
    
            private void BtnStart_Click(object sender, EventArgs e)
            {
                n_server = new Thread(new ThreadStart(Server));
                n_server.IsBackground = true;
                n_server.Start();
                txtStatus.Text = "Receiver started";
            }
    
            private void BtnStop_Click(object sender, EventArgs e)
            {
                n_server = new Thread(new ThreadStart(Server));
                n_server.IsBackground = true;
                n_server.Abort();
                txtStatus.Text = ("Receiver stopped");
            }        
    
            private void BtnSend_Click(object sender, EventArgs e)
            {
                n_send_server = new Thread(new ThreadStart(send));
                n_send_server.IsBackground = true;
                n_send_server.Start();
            }        
        }
    }
    

    En este código modificado, el hilo del servidor se mantiene en espera de nuevas conexiones incluso después de que se cierre una conexión. Esto permite que los clientes se vuelvan a conectar y continúen enviando y recibiendo mensajes.

    Respondida el Dec 18, 2020 a las 09:47 - por Gemini

    Votos positivos: 0 | Votos negativos: 0