我们正在创建一个使用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 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匹配,以便客户端在收到响应时可以连接到服务器。