2

I have built a peer to peer C# video conferencing application that uses a specific TCP port(17500) for audio communication. Currently, on my application interface, I enter the other IP address which has the program opened in order to communicate. What I want to do is to find the IP addresses automatically.

So, I though the best way to achieve this is to obtain the local IP addresses that are using the same TCP port number, 17500. How can I do that ? or is there any other methods getting IP addresses using the same application ?

vcsjones
  • 138,677
  • 31
  • 291
  • 286
0014
  • 893
  • 4
  • 13
  • 40
  • 1
    I don't get it. Why do you need local IP? Don't you need the remote address? – Eser Aug 19 '15 at 19:18
  • @Eser they say local IP address**es** which to me means the local network. – vcsjones Aug 19 '15 at 19:18
  • http://stackoverflow.com/questions/6668810/how-do-i-determine-the-local-host-s-ipv4-addresses – Clay Sills Aug 19 '15 at 19:21
  • It sounds like what you are referring to is port scanning... that's strongly frowned upon. – Michael Bray Aug 19 '15 at 19:21
  • 5
    I would instead implement UDP broadcasting. Your application sends a UDP datagram to the 255.255.255.255 broadcast address. This datagram is then sent to every host in the local network (that's what happens when you send a datagram to 255.255.255.255). Your application also listens for these UDP broadcasts and responds accordingly. For every IP address that responds appropriately, you can assume that its your application and you can try connecting with TCP on your port. Take a look at https://msdn.microsoft.com/en-us/library/tst0kwb1(v=vs.110).aspx – vcsjones Aug 19 '15 at 19:22
  • possible duplicate of [Find the IP address of Running Application over lan](http://stackoverflow.com/q/13761084/11683) – GSerg Aug 19 '15 at 19:22
  • Best way to do in these cases is implement a UDP server which replies to specific port and client application can either broadcast or multicast and get the IP Address as a part of data from the UDP server – sumeet kumar Aug 19 '15 at 19:23
  • @Eser exactly as vcjones said. I`m trying to get the IP addresses that are connected to the same network and using the same application. – 0014 Aug 19 '15 at 19:23
  • @vcsjones Do I have to implement a UDP server for what you suggest ? – 0014 Aug 19 '15 at 19:26
  • Actually no need for UDP, if you have an AD object with in same domain. You can easily find out IP address for given hostname and find out port is listening or not. – Amit Shakya Aug 19 '15 at 19:28
  • @sumeetkumar did you mean an UDP server or UDP service ? because I dont think I need a server to do what I am trying to do... – 0014 Aug 19 '15 at 19:35

3 Answers3

6

As mentioned in comments, you need some kind of peer-discovery protocol.

As many multimedia devices, routers etc. use multicast based discovery protocols like SSDP, I created a similar discovery service sample .

Usage is simple. Just use

Discoverer.PeerJoined = ip => Console.WriteLine("JOINED:" + ip);
Discoverer.PeerLeft= ip => Console.WriteLine("LEFT:" + ip);

Discoverer.Start();

All your clients will use the same code.


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());
            }
        }
    }
}

Now a little bit about the algorithm:

  • Every client multicasts a packet every seconds.

  • if the receiver(every client has it) gets a packet from an IP that isn't in its cache, it will fire PeerJoined method.

  • Cache will expire in 20 seconds. If a client doesn't receive a packet within that duration from another client in cache, it will fire PeerLeft method.

Eser
  • 12,346
  • 1
  • 22
  • 32
  • This code works like a charm! Thank you. The only problem is when one side leaves, the IP address shown on console is not the leavers address its the remaining peers IP address. – 0014 Aug 20 '15 at 17:45
  • For those who wonder how to use the first code segment, run it once the application loads. – 0014 Aug 20 '15 at 17:46
  • @0014 your are right about this minor bug. Instead of using the captured value (`from`) I should have used the argument of `RemovedCallback` while invoking `PeerLeft`. I leave it for future readers... – Eser Aug 20 '15 at 18:32
  • 1
    I tried applying what you mentioned but failed to do. Is there a chance that you might you may correct that minor bug you have mentioned ? – 0014 Aug 20 '15 at 19:43
2

I believe if you are using a peer to peer application to exchange packets, when you need to know if someone "Is Online and Ready for connection", you need to send a broadcast. We can do it easily using an UDP connection.

I'll post an example where you use two methods: one to ask the entire network for ready clients in a broadcast message, and the other will start a listener to answer back broadcast asking message, or start a connection if a response of type "i am here" comes.

Hope it helps!

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!
        }
    }
}
Ismael
  • 622
  • 6
  • 11
-4

Invoke your command prompt to do "netstat -n" and extract the output.

Here is a piece of code taken from a program that I have wrote modified to fit your requirements. You will still need to further process the data to get the IP addresses

        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
Matty2
  • 55
  • 6
  • netstat -n will give me the ports I am using which I already know. I need the IP addresses of the devices using my application. How am I suppose to find the IP addresses with this information ? – 0014 Aug 19 '15 at 20:25
  • If you do netstat -n on your command prompt now, you will know what to remove and filter. 1.Remove the header of the output(Reject the first line) 2.remove all lines that repeats 127.0.0.1 twice 3.Get lines that contains :17500 4.Only accept lines with the string "TCP" and "ESTABLISHED" 5.Remove the strings "TCP", "ESTABLISHED", , ":17500", and trim it – Matty2 Aug 19 '15 at 20:37
  • You have to run that code on your server. If you are using peer-to-peer(no server). You need to use port scanning, list out all the ip addresses in your subnet that you want to scan(some algorithm that can list all possible IP addresses in the subnet) and scan for open ports that is 17500. Those with the open ports are running your application. There is a port scanning tool you can invoke in your program https://nmap.org/ – Matty2 Aug 19 '15 at 20:48
  • Sorry I got curious and tried what you have suggested, unfortunately it doesn't work. I opened my application on two different computers within same local network, then typed in command prompt netstat -n on both as well. There is no IP data of other computers other than itself... – 0014 Aug 20 '15 at 18:21
  • IT works only when you have a server and you are doing it on the server – Matty2 Aug 21 '15 at 11:10