C# 如何获取运行我的程序的本地网络上主机的IP地址
我构建了一个对等C视频会议应用程序,它使用特定的TCP端口17500进行音频通信。目前,在我的应用程序界面上,我输入了另一个IP地址,该地址打开了程序以便通信。我想做的是自动查找IP地址C# 如何获取运行我的程序的本地网络上主机的IP地址,c#,sockets,tcp,port,p2p,C#,Sockets,Tcp,Port,P2p,我构建了一个对等C视频会议应用程序,它使用特定的TCP端口17500进行音频通信。目前,在我的应用程序界面上,我输入了另一个IP地址,该地址打开了程序以便通信。我想做的是自动查找IP地址 因此,我认为实现这一点的最佳方法是获取使用相同TCP端口号17500的本地IP地址。我该怎么做?或者是否有其他方法使用相同的应用程序获取IP地址?我相信如果您使用对等应用程序交换数据包,当您需要知道某人是否在线并准备好连接时,您需要发送广播。我们可以很容易地使用UDP连接 我将发布一个示例,其中您使用两种方法:
因此,我认为实现这一点的最佳方法是获取使用相同TCP端口号17500的本地IP地址。我该怎么做?或者是否有其他方法使用相同的应用程序获取IP地址?我相信如果您使用对等应用程序交换数据包,当您需要知道某人是否在线并准备好连接时,您需要发送广播。我们可以很容易地使用UDP连接 我将发布一个示例,其中您使用两种方法:一种是在广播消息中向整个网络询问准备就绪的客户端,另一种是启动侦听器以回复广播询问消息,或者如果出现I am here类型的响应,则启动连接 希望有帮助
public sealed class UdpUtility
{
// Our UDP Port
private const int broadcastPort = 11000;
// Our message to ask if anyone is ready for connection
private const string askMessage = "ARE ANYONE OUT THERE?";
// Our answer message
private const string responseMessage = "I AM HERE!";
// We use this method to look for a client to connect with us.
// It will send a broadcast to the network, asking if any client is ready for connection.
public void SendBroadcastMessage()
{
var udp = new UdpClient(broadcastPort);
var endpoint = new IPEndPoint(IPAddress.Broadcast, broadcastPort);
try
{
var bytes = Encoding.ASCII.GetBytes(askMessage);
udp.Send(bytes, bytes.Length, endpoint);
}
catch (Exception ex)
{
// Treat your connection exceptions here!
}
}
// This method will start a listener on the port.
// The client will listen for the ask message and the ready message.
// It can then, answer back with a ready response, or start the TCP connection.
public void ListenBroadcastMessage()
{
var udp = new UdpClient(broadcastPort);
var endpoint = new IPEndPoint(IPAddress.Broadcast, broadcastPort);
bool received = false;
try
{
while (!received)
{
// We start listening broadcast messages on the broadcast IP Address interface.
// When a message comes, the endpoing IP Address will be updated with the sender IP Address.
// Then we can answer back the response telling that we are here, ready for connection.
var bytes = udp.Receive(ref endpoint);
var message = Encoding.ASCII.GetString(bytes);
if (message == askMessage)
{
// Our client received the ask message. We must answer back!
// When the client receives our response, his endpoint will be updated with our IP Address.
// The other client can, then, start the TCP connection and do the desired stuff.
var responseBytes = Encoding.ASCII.GetBytes(responseMessage);
udp.Send(responseBytes, responseBytes.Length, endpoint);
}
else if (message == responseMessage)
{
// We received a connection ready message! We can stop listening.
received = true;
// We received a response message!
// We can start our TCP connection here and do the desired stuff.
// Remember: The other client IP Address (the thing you want) will be on the
// endpoint object at this point. Just use it and start your TCP connection!
}
}
}
catch (Exception ex)
{
// Treat your connection exceptions here!
}
}
}
调用命令提示符执行netstat-n并提取输出 下面是一段代码,取自我编写的一个程序,经过修改以满足您的需求。您仍然需要进一步处理数据以获得IP地址
Process netP = new Process();
ProcessStartInfo netPI = new ProcessStartInfo();
netPI.FileName = "cmd";
netPI.UseShellExecute = false;
netPI.RedirectStandardOutput = true;
netPI.RedirectStandardInput = true;
netPI.RedirectStandardError = true;
netPI.CreateNoWindow = true;
netP.StartInfo = NetPI;
netP.Start();
while (!netP.Start())
Thread.Sleep(100);
StreamWriter sW = netP.StandardInput;
StreamReader sR = netP.StandardOutput;
sW.WriteLine("netstat -n")
sW.Close();
string data = sR.ReadToEnd();
sR.Close();
//Do some further processing to filter out the addresses and extract
正如评论中提到的,您需要某种对等发现协议 由于许多多媒体设备、路由器等使用基于多播的发现协议,例如,我创建了一个类似的发现服务示例 用法很简单。只用
Discoverer.PeerJoined = ip => Console.WriteLine("JOINED:" + ip);
Discoverer.PeerLeft= ip => Console.WriteLine("LEFT:" + ip);
Discoverer.Start();
您的所有客户端都将使用相同的代码
现在介绍一下算法:
每个客户端每秒钟多播一个数据包
如果receiverevery客户端从不在其缓存中的IP获取数据包,它将触发PeerJoined方法
缓存将在20秒后过期。如果一个客户端在该持续时间内没有从缓存中的另一个客户端接收到数据包,它将触发PeerLeft方法
我不明白。为什么您需要本地IP?你不需要远程地址吗?@Eser他们说的是本地IP地址,对我来说就是本地网络。听起来你指的是端口扫描。。。这是强烈反对的。我会改为实现UDP广播。应用程序向255.255.255.255广播地址发送UDP数据报。然后将该数据报发送到本地网络中的每台主机,这就是将数据报发送到255.255.255.255时发生的情况。您的应用程序还侦听这些UDP广播并相应地作出响应。对于每个适当响应的IP地址,您可以假设它是您的应用程序,您可以尝试在端口上连接TCP。看看netstat-n,它会给我一些我已经知道的端口。我需要使用我的应用程序的设备的IP地址。如果现在在命令提示符下执行netstat-n,您将知道删除和过滤什么。1.删除输出的标题弹出第一行2.删除所有重复127.0.0.1两次的行3.获取包含:17500的行4.仅接受带有字符串TCP和已建立的行5.删除字符串TCP,已建立的::17500,并修剪它您必须在服务器上运行该代码。如果您使用的是peer-to-peerno服务器。您需要使用端口扫描,列出要扫描的子网中的所有ip地址。某些算法可以列出子网中所有可能的ip地址,并扫描17500的开放端口。具有开放端口的端口正在运行您的应用程序。有一个端口扫描工具,你可以在你的程序调用抱歉,我很好奇,并尝试了你的建议,不幸的是,它不工作。我在同一个本地网络中的两台不同的计算机上打开了我的应用程序,然后在这两台计算机上输入命令提示符netstat-n。除了它自己,没有其他计算机的IP数据…只有当你有一台服务器并且你在服务器上运行时,它才会工作。这段代码就像一个符咒!非常感谢。唯一的问题是,当一方离开时,控制台上显示的IP地址不是离开者地址,而是其他对等方的IP地址。对于那些想知道如何使用第一个代码段的人,请在应用程序加载后运行它。@0014您对这个小错误的看法是正确的。我应该在调用PeerLeft时使用RemovedCallback的参数,而不是使用从中捕获的值。我把它留给未来的读者…我试着应用你提到的东西,但没有成功。您是否有可能纠正您提到的那个小错误?
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Caching; // add this library from the reference tab
using System.Text;
using System.Threading.Tasks;
namespace SO
{
public class Discoverer
{
static string MULTICAST_IP = "238.212.223.50"; //Random between 224.X.X.X - 239.X.X.X
static int MULTICAST_PORT = 2015; //Random
static UdpClient _UdpClient;
static MemoryCache _Peers = new MemoryCache("_PEERS_");
public static Action<string> PeerJoined = null;
public static Action<string> PeerLeft = null;
public static void Start()
{
_UdpClient = new UdpClient();
_UdpClient.Client.Bind(new IPEndPoint(IPAddress.Any, MULTICAST_PORT));
_UdpClient.JoinMulticastGroup(IPAddress.Parse(MULTICAST_IP));
Task.Run(() => Receiver());
Task.Run(() => Sender());
}
static void Sender()
{
var IamHere = Encoding.UTF8.GetBytes("I AM ALIVE");
IPEndPoint mcastEndPoint = new IPEndPoint(IPAddress.Parse(MULTICAST_IP), MULTICAST_PORT);
while (true)
{
_UdpClient.Send(IamHere, IamHere.Length, mcastEndPoint);
Task.Delay(1000).Wait();
}
}
static void Receiver()
{
var from = new IPEndPoint(0, 0);
while (true)
{
_UdpClient.Receive(ref from);
if (_Peers.Add(new CacheItem(from.Address.ToString(), from),
new CacheItemPolicy() {
SlidingExpiration = TimeSpan.FromSeconds(20),
RemovedCallback = (x) => { if (PeerLeft != null) PeerLeft(x.CacheItem.Key); }
}
)
)
{
if (PeerJoined != null) PeerJoined(from.Address.ToString());
}
Console.WriteLine(from.Address.ToString());
}
}
}
}