我们正在创建一个使用TCP进行主要通信和UDP进行广播的系统 . 客户端在服务器侦听其广播时广播其状态,并响应确认客户端使用接收消息的IPEndpoint进行连接 . 这里的问题是当创建服务器时,它从Dns.GetHostAddresses()方法获取IP地址并将其设置为其IP并使用该IP创建TCP套接字 . 但是,UdpClient会自行执行并在我的计算机上发送不同的IPEndpoint(例如适配器2),因此当客户端尝试连接到TCP流时, endpoints 不存在 .

我不确定如何在这些情况下获得相同的IPEndpoint,因为我不确定UdpClient类如何返回它 . 我也不确定是否应该在实际的确认数据包中发送 endpoints ,但我不应该因为UdpReceiveResult应该返回服务器计算机的IPEndpoint .

以下是一些代码的示例:

GetIP4Address:

public static string GetIP4Address()
    {
        //Retrieve all ip addresses associated with this computer (like when you invoke "ipconfig" in cmd)
        IPAddress[] hostIpAddresses = Dns.GetHostAddresses(Dns.GetHostName());

        //We want to look through all of the IP addresses and search for the IPv4 address and return it
        foreach (IPAddress ip in hostIpAddresses)
        {
            if (ip.AddressFamily.Equals(AddressFamily.InterNetwork))
            {
                return ip.ToString();
            }
        }

        //If it does not exist, we can assume we are offline and to return the localhost address
        return Constants.LOCAL_IP;
    }

UDP ReceivePacket任务:

private async Task<Tuple<Packet, IPEndPoint>> ReceivePacket(UdpClient con)
    {
      byte[] data;
      UdpReceiveResult result = await con.ReceiveAsync();
      data = result.Buffer;
      Packet packet = Packet.Deserialize(data);
      return new Tuple<Packet, IPEndPoint>(packet, result.RemoteEndPoint);
    }

使用ReceivePacket初始化客户端/服务器(握手):

private async Task HandShake()
    {
        // We look for a server up to MAX_RETRY times.
        int retryCounter = 0;
        UdpClient broadcast = new UdpClient();

        // Here is why we need UPD to accomplish this task. Because we need to broadcast
        // over the network asking for a server
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, Constants.CONNECTION_PORT);

        // We need to send a SYN packet letting know to the server (If exists) that we are asking
        // for a handshake. We serialize the packet
        Packet synPacket = new Packet();
        synPacket.Flags = PacketFlag.SYN;
        byte[] rawSYNPacket = Packet.Serialize(synPacket);

        do
        {
            // Sending our "BROADCAST"
            broadcast.Send(rawSYNPacket, rawSYNPacket.Length, endPoint);
            txtMessagesBox.Text += $"Waiting a server #{retryCounter}\n";

            // We wait for a response on a separate thread.
            // The receive method is a blocking operation so we wrote an extension method to
            // create an asynchronous method with a timeout.
            var packetTuple = await ReceivePacket(broadcast).WithTimeout(TimeSpan.FromSeconds(SEARCH_SERVER_TIMEOUT));

            // If no packet is received we try it one more time up to MAX_RETRY times
            if (packetTuple == null)
            {
                ++retryCounter;
                continue;
            }
            // If we receive an ACK packet then a server exists and we need to configure the application as client
            else if (packetTuple.Item1.Flags == PacketFlag.ACK)
            {
                this.StartClient(packetTuple.Item2);
                return;
            }
        }
        while (retryCounter < MAX_RETRY);

        // If no response then the application must be configured as a server
        txtMessagesBox.Text += "Ok, I'll be the server\n";
        this.StartServer();
    }

我需要知道如何使这些IPEndpoints匹配,以便客户端在收到响应时可以连接到服务器 .