Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET是否获取UdpClient为本地计算机使用的正确IPEndpoint?_.net_Sockets_Tcp_Udp - Fatal编程技术网

.NET是否获取UdpClient为本地计算机使用的正确IPEndpoint?

.NET是否获取UdpClient为本地计算机使用的正确IPEndpoint?,.net,sockets,tcp,udp,.net,Sockets,Tcp,Udp,我们正在创建一个系统,使用TCP进行主通信,使用UDP进行广播。客户端广播其状态,而服务器侦听其广播,并通过确认客户端使用接收到的消息的IPEndpoint进行连接来作出响应。这里的问题是,当创建服务器时,它从Dns.GetHostAddresses()方法获取IP地址,并将其设置为其IP,然后使用该IP创建TCP套接字。但是,UdpClient执行自己的操作并在我的计算机上发送不同的IPEndpoint(例如适配器2),因此当客户端尝试连接到TCP流时,端点不存在 我不确定在这些情况下如何获得

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

我不确定在这些情况下如何获得相同的IPEndpoint,因为我也不确定UdpClient类如何返回它。我也不确定是否应该在实际确认数据包中发送端点,但我不应该,因为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接收数据包任务:

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);
    }
private async Task ReceivePacket(UdpClient-con)
{
字节[]数据;
UdpReceiveResult结果=等待con.ReceiveAsync();
数据=结果缓冲区;
数据包=数据包。反序列化(数据);
返回新元组(数据包、结果、RemoteEndPoint);
}
使用ReceivePacket初始化客户端/服务器(握手):

专用异步任务握手()
{
//我们寻找最多重试次数的服务器。
int-retryCounter=0;
UdpClient broadcast=新的UdpClient();
//这就是为什么我们需要UPD来完成这项任务,因为我们需要广播
//通过网络请求服务器
IPEndPoint端点=新IPEndPoint(IPAddress.Broadcast,Constants.CONNECTION_PORT);
//我们需要发送一个SYN数据包,让它知道我们正在请求的服务器(如果存在)
//为了握手,我们将数据包序列化
数据包synPacket=新数据包();
synPacket.Flags=PacketFlag.SYN;
字节[]rawSYNPacket=Packet.Serialize(synppacket);
做
{
//发送我们的“广播”
发送(rawSYNPacket,rawSYNPacket.Length,endPoint);
txtMessagesBox.Text+=$“正在等待服务器#{retryCounter}\n”;
//我们在另一个线程上等待响应。
//receive方法是一个阻塞操作,因此我们为它编写了一个扩展方法
//创建一个具有超时的异步方法。
var packetTuple=wait ReceivePacket(广播)。带有超时(TimeSpan.FromSeconds(搜索服务器超时));
//如果没有收到数据包,我们将重试一次,最多重试一次
if(packetTuple==null)
{
++回收计数器;
继续;
}
//如果我们收到一个ACK数据包,那么服务器就存在,我们需要将应用程序配置为客户端
else if(packetTuple.Item1.Flags==PacketFlag.ACK)
{
this.StartClient(packetTuple.Item2);
返回;
}
}
while(重试计数器<最大重试次数);
//如果没有响应,则必须将应用程序配置为服务器
txtMessagesBox.Text+=“好的,我将是服务器\n”;
this.StartServer();
}

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

确保您的TCP服务器正在侦听UDP服务器正在侦听广播的同一本地IP。并确保UDP服务器使用接收广播的相同本地IP发送每个ack。听起来您没有正确执行所有这些操作,但是您没有显示任何服务器端代码。我的问题是,我不知道如何使用UDP服务器正在侦听的同一本地IP,因为我从未实际将UDPClient绑定到IPEndpoint,这就是您的问题。在服务器端,需要将UDP侦听器绑定到TCP服务器绑定到的同一IP。当UDP侦听器接收到广播时,它知道它正在侦听的IP端点,并且知道发送方的IP端点。使用接收广播的相同UDP对象将ACK发送回发送方。当发送方收到ACK时,远程端点将是发送ACK的UDP侦听器的端点,并且扩展为相应的TCP服务器。如果TCP服务器绑定到多个IP,请为每个IP创建单独的UDP侦听器。
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();
    }