gpt4 book ai didi

c# - 如何获取正在监听特定端口 LAN 的所有服务器的 IP?

转载 作者:行者123 更新时间:2023-12-04 05:54:22 24 4
gpt4 key购买 nike

如何获取在 LAN 中监听特定端口(例如:9090)的所有服务器 IP
我已经阅读了一些关于多播的基本信息,anycast , unicastbroadcast看起来像 broadcast是适用于我的应用程序的。
我在想两个想法..

  • 使用 TCP 协议(protocol)在端口 9090 上并行连接到所有 IP 地址(192.168.1.1-254),并为连接超时设置一点时间。只是为了检查是否有任何回应。 (但这似乎不是一个好主意)
  • 使用 UDP 协议(protocol)并广播诸如“hello”之类的消息并检查响应,然后获取所有响应的 IP 地址。

    那么我应该选择哪个想法,有更好的想法吗?
    我还想知道我的广播消息是否被接收到服务器以及如何获取它的 IP 地址。
  • 最佳答案

    我已经使用 TCP 来搜索所有正在监听特定端口的服务器。
    它不是一个空闲的解决方案,但它对我有用。

    我创建了一个带有公共(public)函数 Initialize 的 userControl 来传递我要扫描服务器的端口。

    enter image description here

    public ServerDiscovery()
    {
    InitializeComponent();
    // statusLabel.Image = imageState.Images[2];
    timer.Elapsed += timer_tick;
    }
    int port = 0;
    bool busy = false; // to tell that the function is busy with scanning.
    public void Initialize(int port)
    {
    this.port = port;
    }

    System.Timers.Timer timer = new System.Timers.Timer(5000);
    List<SocketAsyncEventArgs> list = new List<SocketAsyncEventArgs>();
    // this list to hold all sockets that created to connect to IP .. to DISPOSE it later
    HashSet<string> usedIP = new HashSet<string>();
    //usedIP will be explained later.

    public IPEndPoint getAddress()
    { //this function to get the IPEndPoint of the selected server from listview.
    if (listServer.SelectedItems.Count > 0)
    {
    if (listServer.SelectedItems[0].ImageIndex == 0)
    {
    ListViewItem item = listServer.SelectedItems[0];
    IPEndPoint ep = new IPEndPoint(IPAddress.Parse(item.SubItems[1].Text), port);
    return ep;
    }
    }
    return null;
    }

    public void Refresh() //to scan for servers
    {
    if (!busy)
    {
    usedIP.Clear();
    listServer.Items.Clear();
    // statusLabel.Text = "Scanning for servers.";
    // statusLabel.Image = Image.FromFile("loading.gif");
    // btnRefresh.Enabled = false;
    busy = true;
    timer.Start();
    IPAddress[] IpA = Dns.GetHostByName(Dns.GetHostName()).AddressList;
    for (int j = 0; j < IpA.Length ; j++)
    {
    if (IpA[j].AddressFamily == AddressFamily.InterNetwork) // to make sure it's an IPV4
    {
    string scanIP = IpA[j].ToString().Substring(0, IpA[j].ToString().LastIndexOf(".")) + ".";
    if (!usedIP.Contains(scanIP))
    //usedIP is a hashset that holds the first 3 parts on an ip (ex:"192.168.1." from "192.168.1.30") i used this to avoid scanning the same ip addresses more than once .. like if i had a wireless network ip ("192.168.1.5") and an Ethernet Network ip ("192.168.1.5"). so with that hashset it will scan once.
    {
    usedIP.Add(scanIP);
    Parallel.For(1, 255, i =>
    {
    Scan(scanIP + i);
    });
    }
    }
    }
    }
    }

    private void Scan(string ipAdd)
    {
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    SocketAsyncEventArgs e = new SocketAsyncEventArgs();
    e.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(ipAdd), port);
    e.UserToken = s;
    e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);
    list.Add(e); // add the created socket to a list to dispose when time is up.
    s.ConnectAsync(e);
    }

    private void e_Completed(object sender, SocketAsyncEventArgs e)
    {
    if (e.ConnectSocket != null) //if there's a responce from the server [e.ConnectSocket] will not be equal null.
    {
    StreamReader sr = new StreamReader(new NetworkStream(e.ConnectSocket));
    ListViewItem item = new ListViewItem();
    string[] cmd = sr.ReadLine().Split('<'); in my server constructor this line will receive a string like "PC_NAME<Available" ..
    item.Text = cmd[0];
    item.SubItems.Add(((IPEndPoint)e.RemoteEndPoint).Address.ToString());
    item.SubItems.Add(cmd[1]);
    if (cmd[1] == "Busy")
    item.ImageIndex = 1;
    else
    item.ImageIndex = 0;
    AddServer(item);
    list.Remove(e); //active server should be remove from the list that holds the sockets and disposed.. because there's no need to keep connection after showing that this server is active.
    ((Socket)e.UserToken).Dispose();
    }
    }

    delegate void AddItem(ListViewItem item);
    private void AddServer(ListViewItem item)
    {
    if (InvokeRequired)
    {
    Invoke(new AddItem(AddServer), item); //just to add an item from a background thread.
    return;
    }
    listServer.Items.Add(item);
    }

    private void timer_tick(object sender, EventArgs e)
    {
    busy = false; //when time's up .. set busy to false so we can scan again
    timer.Stop();
    foreach (var s in list) //dispose all sockets that's trying to connect and waiting for a response
    {
    try
    {
    ((Socket)s.UserToken).Dispose();
    }
    catch { }
    }
    //this.Invoke((MethodInvoker)delegate // for design
    // {
    // btnRefresh.Enabled = true;
    // btnRefresh.BorderStyle = Border3DStyle.Raised;
    // statusLabel.Text = "Ready.";
    // statusLabel.Image = imageState.Images[2];
    // });
    }

    private void btnRefresh_Click(object sender, EventArgs e)
    {
    // btnRefresh.BorderStyle = Border3DStyle.Sunken;
    Refresh();
    }

    // private void listServer_KeyUp(object sender, KeyEventArgs e)
    // {
    // if (e.KeyCode == Keys.F5)
    // {
    // btnRefresh_Click(sender, (EventArgs)e);
    // }
    // }


    }

    同样,这不是一个适用于任何情况的理想解决方案,但对我来说效果很好。

    关于c# - 如何获取正在监听特定端口 LAN 的所有服务器的 IP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9696855/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com