Pergunta

É possível obter dois programas distintos para se comunicar no mesmo computador (somente one-way) sobre UDP através de localhost / 127 ... compartilhando a mesma porta #?

Estamos trabalhando em um projeto de estudante em que precisamos enviar pacotes UDP contendo alguns telemetria entre dois computadores. O programa que gera esses pacotes é proprietário, mas eu estou trabalhando no programa receptor-me com C # usando System.Net.Sockets.UdpClient e System.Net.IPEndPoint .

Esta multa trabalha durante as reuniões do nosso grupo quando temos vários computadores ligados em que podemos executar os dois programas separadamente. Mas não é muito útil quando estou em casa e tentando expandir o programa de processamento de telemetria, como eu só tenho um computador (eu preciso de um feed para testar o programa de processamento). Não consigo instalar o programa em qualquer um dos computadores da escola também.

Quando tento executar os dois programas no meu computador ao mesmo tempo (começando meu programa passado) eu recebo um SocketException dizendo que apenas uma única utilização de cada porta é normalmente permitido. O que me leva a acreditar que deve haver alguma maneira de compartilhar a porta (embora faz sentido que apenas um único programa pode usar a porta em um computador a qualquer momento, não tenho problemas para executar vários navegadores de internet ao mesmo tempo (e eu suponha que eles usam a porta 80 para http)).

reeditar do EDIT:

sipwiz estava certo, e graças a Kalmi para o ponteiro para UdpClient.Client.Bind (). Na época, porém, estamos pensando em usar outro programa que gera pacotes similares, e com o qual somos capazes de porta share com no mesmo computador usando a minha primeira abordagem (embora ingênuo) com o cliente UDP obrigatório em ctor. Desculpe por ter que desmarcar sua resposta, sysrqb.

Foi útil?

Solução

Eu não esperava que isso seja possível, mas .. bem .. sipwiz estava certo.

Pode ser feito muito facilmente. (Resposta Por favor votação de sipwiz up!)

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);

Outras dicas

Você pode vincular a uma porta várias vezes usando a opção de socket ReuseAddress.

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

Você precisará configurar a mesma opção no soquete do servidor UDP também.

Aqui está o código completo a partir das respostas por Tarnay Kálmán e sipwiz:

O código do 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();
        }
    }
}

O código do 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();
        }
    }
}

Você pode ser capaz de colocar vários endereços IP na placa de rede, ou de auto-retorno, e se ligam ao servidor e cliente para diferentes endereços IP?

Ou então a abordagem de máquina virtual vai certamente funcionar.

Somente um programa pode ligamento a uma porta de cada vez. Vários programas podem Conectar para uma porta em outro sistema de, mas a porta local seus diferentes navegadores web se comprometeram a é atribuído aleatoriamente.

A menos que você quiser fazer alguma comunicação entre processos feio ou packet sniffing, não há nenhuma maneira de ter vários programas ligados a uma porta.

Meu conselho: não passar o número da porta para o construtor UdpClient. Do documentação, (um pouco esparsos, eu sei ...) parece que se você fizer isso, o UdpClient tentará ligamento para que a porta (que, como sysrqb mencionado, não é permitido). (Se você não fizer isso, eu acredito que o UdpClient irá escutar uma porta aleatória para todas as respostas. Você também pode escolher uma porta que você sabe ser não utilizado.)

Quando você chamar Connect () que você precisa para passar o número da porta do servidor é ouvindo on.

ligam os dois programas, ou seja, o emissor eo receptor para a mesma porta sobre os localhost.dats a resposta simples.

Mesmo alterar seu código para que eu possa passar em um endereço IP que recebe a mesma mensagem de erro, parece que você não pode vincular à mesma porta e apenas uma porta pode ser usada aqui é o código de exemplo que eu usei o seu exemplo e alterou-o para capturar o meu ip da minha máquina local .. Endereço_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

este irá produzir a exceção no Bind () método .. desculpe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top