Pregunta

¿Es posible obtener dos programas separados para comunicarse en el mismo equipo (de un solo sentido) sobre UDP a través de localhost / 127 ... al compartir el mismo puerto #?

Estamos trabajando en un proyecto de estudiantes en la que tenemos que enviar paquetes UDP contienen alguna telemetría entre dos ordenadores. El programa que genera estos paquetes es propietario, pero estoy trabajando en el programa receptor mismo con C # utilizando System.Net.Sockets.UdpClient y System.Net.IPEndPoint .

Esto funciona bien durante las reuniones de nuestro grupo cuando tenemos varios ordenadores conectados en los que podemos ejecutar los dos programas por separado. Pero no es muy útil cuando estoy en casa y tratando de ampliar el programa de procesamiento de telemetría ya que sólo tengo un ordenador (necesito una alimentación para probar el programa de procesamiento). No puedo instalar el programa en cualquiera de las computadoras de la escuela tampoco.

Cuando trato de ejecutar ambos programas en el ordenador al mismo tiempo (a partir de mi último programa) me sale un SocketException diciendo que sólo un único uso de cada puerto es normalmente permitido. Lo que me lleva a creer que debe haber alguna manera de compartir el puerto (aunque tiene sentido que un solo programa puede utilizar el puerto en un ordenador en un momento dado, no tengo problemas para ejecutar múltiples navegadores de Internet al mismo tiempo (y yo supongamos que utilizan el puerto 80 para HTTP)).

reeditar del EDIT:

sipwiz tenía razón, y gracias a Kalmi para el puntero a UdpClient.Client.Bind (). En ese momento, sin embargo, estamos considerando el uso de otro programa que genera paquetes similares, y con el que somos capaces de compartir el puerto con el mismo equipo que utiliza mi acercamiento primera (aunque ingenua) con el cliente UDP vinculante en el ctor. Lo siento por tener que quitar la marca de su respuesta, sysrqb.

¿Fue útil?

Solución

No esperaba que esto sea posible, pero .. bueno .. sipwiz que era correcto.

Se puede hacer muy fácilmente. (Por favor, vote de sipwiz respuesta arriba!)

IPEndPoint localpt = new IPEndPoint(IPAddress.Any, 6000);

//Failed try
    try
    {
        var u = new UdpClient(5000);
        u.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

        UdpClient u2 = new UdpClient(5000);//KABOOM
        u2.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    }
    catch (Exception)
    {
        Console.WriteLine("ERROR! You must call Bind only after setting SocketOptionName.ReuseAddress. \n And you must not pass any parameter to UdpClient's constructor or it will call Bind.");
    }

//This is how you do it (kudos to sipwiz)
    UdpClient udpServer = new UdpClient(localpt); //This is what the proprietary(see question) sender would do (nothing special) 

    //!!! The following 3 lines is what the poster needs...(and the definition of localpt (of course))
    UdpClient udpServer2 = new UdpClient();
    udpServer2.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    udpServer2.Client.Bind(localpt);

Otros consejos

Puede unirse a un puerto varias veces utilizando la opción de conector ReuseAddress.

UdpClient udpClient = new UdpClient();
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

Usted tendrá que ajustar la misma opción en el socket del servidor UDP también.

Este es el código completo de las respuestas de Tarnay Kálmán y sipwiz:

El código del servidor:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace UdpBroadcastTest
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("Sender");
            // This constructor arbitrarily assigns the local port number.

            UdpClient udpClient = new UdpClient();
            udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            udpClient.Connect("localhost", 11000);
            try
            {
                string message = String.Empty;
                do
                {
                    message = Console.ReadLine();
                    // Sends a message to the host to which you have connected.
                    Byte[] sendBytes = Encoding.ASCII.GetBytes(message);

                    udpClient.Send(sendBytes, sendBytes.Length);
                } while (message != String.Empty);

                udpClient.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.WriteLine("Press Any Key to Continue");
            Console.ReadKey();
        }
    }
}

El código de cliente:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace UdpReciever
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Receiver");
            // This constructor arbitrarily assigns the local port number.
            UdpClient udpClient = new UdpClient();
            udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, 11000));
            try
            {
                //IPEndPoint object will allow us to read datagrams sent from any source.
                IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

                string message = String.Empty;
                do
                {

                    // Blocks until a message returns on this socket from a remote host.
                    Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
                    message = Encoding.ASCII.GetString(receiveBytes);

                    // Uses the IPEndPoint object to determine which of these two hosts responded.
                    Console.WriteLine("This is the message you received: " +
                                                 message);
                    //Console.WriteLine("This message was sent from " +
                    //                            RemoteIpEndPoint.Address.ToString() +
                    //                            " on their port number " +
                    //                            RemoteIpEndPoint.Port.ToString());
                }
                while (message != "exit");
                udpClient.Close();
                //udpClientB.Close();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.WriteLine("Press Any Key to Continue");
            Console.ReadKey();
        }
    }
}

Usted puede ser capaz de poner varias direcciones IP en la tarjeta de red o de bucle de retorno, y enlazar el servidor y el cliente para diferentes direcciones IP?

O de lo contrario el enfoque de máquina virtual será definitivamente el trabajo.

Sólo un programa puede bind a un puerto a la vez. Múltiples programas pueden connect a un puerto en otro sistema de, pero el puerto local sus diferentes navegadores web se han obligado a está asignado al azar.

A menos que usted quiere hacer algún tipo de comunicación entre procesos feo o la detección de paquetes, no hay manera de tener múltiples programas ligados a un puerto.

Mi consejo: no deje pasar el número de puerto en el constructor UdpClient. Desde el , (algo escasa, lo sé ...) se ve como si lo hace, la UdpClient tratará de bind a ese puerto (que, como se mencionó sysrqb, no está permitido). (Si no lo hace, creo que el UdpClient va a escuchar en un puerto aleatorio para cualquier respuesta. También podría escoger un puerto que sabes que es utilizada.)

Cuando se llama a connect () que necesita para aprobar el número de puerto del servidor es escuchar activado.

unir los dos programas, es decir, el emisor y el receptor en el mismo puerto en los localhost.dats la respuesta simple.

Incluso cambiar su código para que me puede pasar en una dirección IP que recibe el mismo mensaje de error aparece que no se puede enlazar con el mismo puerto y un solo puerto se puede utilizar aquí es el código de ejemplo he usado el ejemplo y lo alteró para capturar mi ip de mi máquina local ..               Dirección IP ipAddress = Dns.Resolve (Dns.GetHostName ()) AddressList [0].;             IPEndPoint ipLocalEndPoint = new IPEndPoint (ipAddress, 11000);

        //IPEndPoint localpt = new IPEndPoint(ipLocalEndPoint);

        UdpClient udpServer = new UdpClient(ipLocalEndPoint);
        udpServer.Client.SetSocketOption(
            SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        udpServer.Connect(ipLocalEndPoint);
        UdpClient udpServer2 = new UdpClient();
        udpServer2.Client.SetSocketOption(
            SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

        udpServer2.Client.Bind(ipLocalEndPoint); // <<---------- Exception here

esto producirá la excepción en el método bind () .. lo siento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top