What is the easiest way to find the next unused IP address on a local adaptors subnet?
IPAddress GetNextFreeIP(NetworkInterface intface)
{
...?
}
Update
I've written a BOOTP/TFTP server that could be used in many different scenarios (cross-over cable, small private network, large corporate network). I have to give the small embedded system I'm updating an IP address and would like to find a spare one for it to use...
If you have DHCP-managed IP ranges, you have an instance you can talk to - the DHCP server (like David recommended)
If you don't have managed IP ranges and no other instance you can talk to, there is no reliable way to tell if an IP is used or unused. IP does not offer such a service itself.
Apart from asking the DHCP-server, I guess you could do a broadcast ping on the subnet and collect the responses from all computers and simply sort the IP-addresses to find the next one. This assumes, of course, that all devices are on-line and responds to broadcasts. So in a pretty controlled environment, this could work.
The short answer is you can't, as Thorsten79 just said.
A slightly longer answer:
It depends on your network's configuration: how the admin has decided to allocate ip addresses. Usually there's a mix of manually assigned ip addresses for servers, routers etc, and a set of dhcp assigned ip addresses for workstations and such.
If you can talk to the dhcp server you might find out which addresses in the reserved range are free, but for the rest of the addresses you cannot find out.
The more interesting question is what you are trying to accomplish? Perhaps it can be realized in a different manner?
From what I've seen of embedded devices with a TFTP server, they boot up with a hard coded IP Address that is documented. After a set period of time (~3-10 seconds), the boot loader transfers control to the application that reads its configuration and sets the IP Address.
If someone wants to use the boot loader to load new firmware, then they need to read the documentation, make sure that IP Address is reachable (on the same subnet), reboot the device, and TFTP the application to the device.
You are all technically right when you say there is no way to ensure an IP isn't being used. But I've decided to rely on this for now...
public static IPAddress FindNextFree(this IPAddress address)
{
IPAddress workingAddress = address;
Ping pingSender = new Ping();
while (true)
{
byte[] localBytes = workingAddress.GetAddressBytes();
localBytes[3]++;
if (localBytes[3] > 254)
localBytes[3] = 1;
workingAddress = new IPAddress(localBytes);
if (workingAddress.Equals(address))
throw new TimeoutException("Could not find free IP address");
PingReply reply = pingSender.Send(workingAddress, 1000);
if (reply.Status != IPStatus.Success)
{
return workingAddress;
}
}
}
Related
In my program I am getting the local machine's public IP address like this
public static IPAddress getIPAddress()
{
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
foreach (IPAddress addr in localIPs)
{
if (addr.AddressFamily == AddressFamily.InterNetwork)
{
return addr;
}
}
return null;
}
and it worked fine where I live.
Right now I am at a friend's house, and I am connected to internet via Wi-Fi, and this code does not give me my external IP address, it has probably something to do with the router settings, but I am not very familiar with networks...
The router is TP-LINK, and I can access its settings like this
By the way, the 8080 port is exactly the one I need, I only need to be able to access my public IP. How can I do it?
You can make a request to a site like http://icanhazip.com/ to get your external IP address
var request = WebRequest.Create("http://ipv4.icanhazip.com/");
var response = request.GetResponse();
var dataStream = response.GetResponseStream();
var reader = new StreamReader (dataStream);
string myIPAddress = reader.ReadToEnd();
More info here: https://msdn.microsoft.com/en-us/library/456dfw4f%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
There is no sure-fire way to do this that will work 100% of the time. However, there are two methods that will work most of the time.
The first is to use an external STUN server. It's relatively easy to add a configuration entry to your software to allow the user to change the STUN server if this server ever changes or goes down, they can choose another one.. there are many of them out there. A STUN server returns the users IP address back to the caller and is used by most VOIP devices.
The second is to use the built-in Universal Plug-n-Play framework (UPnP) to ask the router for its IP Address. This one, however, depends on the router supporting UPnP and it not being disabled. Additionally, UPnP may not work within a corporate network as there are several layers of routers and firewalls usually. Still, for home users this is typically a good option. There is a .NET based UPnP library here that utilizes the built-in COM based UPnP components in Windows:
http://managedupnp.codeplex.com/
I don't have any examples of how to implement this, but it supposedly has a good documentation library.
What you want is not possible. A router is a proxy of sorts, whereby all traffic must pass through it. The external IP address for all internal devices (including PCs, laptops, tablets, etc), will be the same--the internal IP address what is different. The only way for a device to know its external IP address is either to query the router (which might not be possible), or to query an external source. The port forwarding page you have in your post only shows the router where to redirect incoming traffic on that port, but it will tell the PC nothing as to what its external IP address is--because, generally, to the PC the external IP address is irrelevant.
Writing a chat program (as so many do) and i have found that i would like to be able to get the clients to connect to the server automatically.
However, the IP address of the server would not be permanent, so i cannot just hard-core it into the program
In TCP, I'm looking for some sort of broadcast feature, that allows the client to know where the server is
Any ideas?
EDIT: should have said, this will be a LAN program only - no outside connections
If you are talking about a chat in a LAN and you can't or don't want to use DNS for some reason, you could implement, or find an implementation of, the discovery protocol used by UPnP. The SSDP is based on a UDP broadcast. It is, afaik, not possible to multicast via TCP, because TCP needs a session.
If you want to use the chat server over the internet you have no choice but to use DNS. Look for a dynamic dns provider (I use selfhost.bz). In C# you can then resolve the hostname to an IP address as described in the other answers. If you have a hostname to connect to it will probably be enough to pass that to the socket, though:
socket.Connect("myhostname.selfhost.bz", ...
Edit: Since you say you're in a LAN, a few more details on SSDP. The protocol does way more, than you actually need. If you're thinking of implementing it yourself, don't stick to it exactly. Just make your clients send a broadcast on a specified port. The server permanently listens on that port, answering with a predefined message, once it receives a message. When the client receives that answer, it will know that the sender is a valid server.
Use DNS. Resolve the hostname in your app and connect to the IP it resolves to. You'll need dynamic DNS since you say the IP isn't permanent.
Use the below process to find server IP address
public string GetIPAddress()
{
string strHostName = System.Net.Dns.GetHostName();
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
return ipAddress.ToString();
}
You can also use
Request.ServerVariables["LOCAL_ADDR"];
I had an idea: just get the server to write the IP address/port/whatever to a textfile somewhere on the (public) network, and the clients can read the text file
Obviously, if the text file is not there or empty, no server is running...
Is this such a bad idea?
i've written a simple local messenger with c# for use of myself. now it works over a local network(lan,wifi) and works fine.
now i want to give it to my friend and use it over internet but have no idea how to use different ip except local host.
i'd be grateful for any help.
thanks in advance.
private void InitializeConnection()
{
ipAddr = IPAddress.Parse(txtIp.Text);
tcpServer = new TcpClient();
tcpServer.Connect(ipAddr, 1986);
Connected = true;
UserName = txtUser.Text;
txtIp.Enabled = false;
txtUser.Enabled = false;
txtMessage.Enabled = true;
btnSend.Enabled = true;
btnConnect.Text = "Disconnect";
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(txtUser.Text);
swSender.Flush();
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
this the client part
public ChatServer(IPAddress address)
{
ipAddress = address;
}
private Thread thrListener;
private TcpListener tlsClient;
bool ServRunning = false;
public static void AddUser(TcpClient tcpUser, string strUsername)
{
ChatServer.htUsers.Add(strUsername, tcpUser);
ChatServer.htConnections.Add(tcpUser, strUsername);
SendAdminMessage(htConnections[tcpUser] + " has joined us");
}
and this server part.
Intro
To be able to get another user to connect to a computer of yours, there are a quite a few things you are going to have to do. Hopefully, this should work but networking can get complex in general and not all networks run alike. I assume you are running this behind some sort of router that you have access to. Networking is complex and that really is why this answer is so awfully long (if you are questioning yourself on reading the rest of it). For the most part it is pretty straight and forward, but might take some time.
And before you get started, just a:
Forewarning
Thinking security wise, like almost everything on computers and with networking in general, there is not really something called "entirely safe" (at least as far as I know). As with networking, opening ports is not entirely safe. I'm not a top notch security expert, but by doing this, you are allowing other computers to send and receive data with your computer. This should be safe in your case of just having a simple text chat, but in other cases this might not be the same. With more complex and important cases such as dealing with SSH and FTP, there is more security involved. Just as a warning, make sure to take care when messing with your network, or with computers in general.
Getting Started
Anyways, (if I have not scared you off yet) these are the steps that I had to take to get something like your chat server working:
Forwarding the port on your router
The first thing you are going to have to do is forward or open the port on your router. Well, before you can even do this, there are several things you need to understand about networking:
Basically, your router is what connects your network of computers to the internet and allows connections to be be made through ports. If you don't understand what a port is, it is what is used for internet connections to be made and basically acts like the house number to a street address. It tells where on that street the house it and is more specific than just the street address. In terms of networking, this is a number which tells the specific place the communication is going. The port number ("the house number") is telling where on the computer's IP address ("the street address") to connect.
Specifically, the port number is an 16-bit unsigned integer ranging from 0 to 65535 (but port number 0 actually cannot be used according to Wikipedia) Even though this is a 16-bit unsigned integer which would be a ushort or a UInt16 in C#, when using a TcpClient or a TcpListener, they instead use a signed 32-bit integer instead which is the standard int or a Int32. Also, The port is generally denoted after an IP address with a colon (":"), for example 123.45.67.89:80 but might be different in other cases. This is using IPv4 but there is also IPv6 which I have not yet worked with.
Now, what about forwarding the port and why do you need to do that? What forwarding the port does is forward connections to a certain port on the router to a computer which is behind the router instead. There is not always a simple, straight and forward way to do this since router companies have different ways of accomplishing this. Generally, to figure this out, you can Google for instructions on how to forward the port on your particular router, so for example you can search for "forward port on router company's name router" to find it. To do this, you are probably also going to need a few things before getting started with that:
You are going to need your routers admin user name and password which is generally not (and probably should not be) what is used to connect to it with. If you don't know what it is, whoever setup your router should know. Once you have got this working you are ready to move on.
You are also probably going to need the your computer's local IP address which is used to address the computers in the router's network. To find this, your router will probably tell you what it is, but here are the steps to do it on Windows if you can't seem to find it.
Open up command prompt
Open the run dialog by going to Start >> Run... or by pressing Win+R
Type cmd and press enter
Run ipconfig by typing it in and pressing enter to find your computers IP address
You should see a list of network interface connections
To find the one we are looking for, you want to find the network connection you are using to connect to the internet through your router. It is probably different on computer but in my case its named Wireless LAN adapter Wireless Network Connection since I'm using a laptop. The name, I would assume, probably has LAN in it.
This should not have: Media State . . . . . . . . . . . : Media disconnected listed under it since you need to be connected to your router. If you are not then simply do so.
Instead, there should be IPv4 Address. . . . . . . . . . . : with the IP address of your actual computer listed next to it. This is the IP address of the computer whose port you want to forward. Of course, this might be different if you are using a router using IPv6.
Also, in the process of doing this, your port number that were using may be taken by another process or service. This is okay and easy to fix; you just have to change the port number. You are going to want to trying a high number such as 8500 for example until you find one that works. Once you have that number, just update the port number in your code. To make this even easier it, is much easier to have a constant that stores this such as:
const int Port = 8500;
So then you can have the client connect with:
tcpClient.Connect(ipAddress, Port)
And then have the server listen with
TcpListener tcpListener = new TcpListener(ipAddress, Port);
As with other global variables such as the port number that you might have, it may be better to create a global variable class, but at the same time, that may also introduce other issues by using it such as with global properties with threading. Just a suggestion and a heads up.
Though, once you have managed to complete forwarding the port, you can move on to the much simpler part of getting your friend to actually connect to your server.
Geting your router's IP address
Once you have managed to do all of that, you probably should give your a pat on the back because that is the real actual part of getting your router to cooperate with what you were trying to do. Now you just have you give your IP address, port number, and of course your client program to your friend, so he or she can connect to the server. To get your router's public IP address you can go over to the ironically called website at http://www.whatismyip.com/. Here you can get your public IP address but also make sure that it says "No Proxy Detected" below it. If you are using a proxy, hopefully you know what that is and can connect to the internet without to get your IP address. (Trust me, you don't want me to explain want a proxy is for now)
Now once you have got that, you are going to want to send that IP and also your port number to your friend. To be smart about it, you don't want this publicly displayed as you probably don't want a bunch of random people trying to break into your network. Sending it over IM or email should (hopefully) be fine as long as your friend does not publicly display it. So when sending your IP address, just be smart about it.
Once you have done that, just don't forget to actually start your server! Without your server running, there is no way to communicate to the clients and accept incoming connections. This will save a lot of frustration from accidentally forgetting to.
Conclusion
Hopefully, this will help you be able to create a cool chat program and also understand a few other things in the process. I really wish this was not so long, but networking is really just complicated in for the most part.
Hope this helps you quite a bit!
I have two standalone exe's Parent.exe and Child.exe.
Parent.exe opens Child.exe and some operation are performed in child.exe by user then
child.exe sends back some processed data to Parent.exe. Both exe's stays on same machine
The communication between Child.Exe and Parent.Exe is being done through TCP IP (Socket Programming). For this we need to calculate the Local IP Address, we used to calculate it in the following way :-
string hostname = Dns.GetHostName();
IPHostEntry ipEntry = Dns.GetHostEntry(hostname);
IPAddress[] addr = ipEntry.AddressList;
string FinalIpAddrs = addr[0]
Everything worked fine at XP but with Windows 7 we are facing problem. The below line return Mac Address what is the right way to do it, so that it works on XP and Win7 both?
string FinalIpAddrs = addr[0]
Oh, those wh program and do not know.
You do NOT need to know an IP Address, use 127.0.0.1, which is a local loopback address. SImple like that - it is there for exactly that reason.
Consider being efficient. If that is all same machine, the usage of TCP is bad. Use named pipes, which are a windows integrated commmunciation mechanism that CAN work cross machine, but on the same machine it uses shared memory which is a LOT more efficient than TCP.
Why not just use IPAddress.Loopback (or IPv6Loopback)?
The loopback addresses are designed for communications entirely on the same host.
I'm also guessing that where you say:
The below line return Mac Address
What you actually mean is that it's returning an IPv6 address. There's no way that that code should be able to return a MAC Address.
Is there a specific requirement NOT to use 127.0.0.1? If no, then I'd just use it without any calculations.
I'd like the user to be able to enter the MAC of a computer on the network. Once they've done that, it'll add it to a list. The program will then ping all of those MACs on the list every time the class is called (I know this isn't necessarily possible, but read on).
Normally I'd simply use IP addresses, but they aren't static, and there are a -lot- of devices on the network that I don't care about the connectivity of for this program. If they don't respond, I'd like it to pop up a message box.
NOW, that being said, the only part I'm having trouble with is the actual part where I ping something. I know that an actual "ping" is not possible when it comes to MAC addresses, so how could I check for something like that? Alternatively, if it's easier, I could also accept pinging something based on the computer name.
EDIT: I'd prefer not to have to use things like arp to find the IP addresses of the devices I want. Like I said though, I'm also interested in whether or not it's possible to search for devices by name. Would that work?
If you have a properly administered environment, you should be using names. By properly administered environment, I'm primarily meaning having a DNS server on your local network.
I have something similar running that pings industrial ethernet devices. These are statically assigned addresses, so they don't register themselves with DNS as a DHCP client would. I had our DNS administrator create records for them so I can just use their name. You'll be better off in the long run as two years from now you're going to have NO idea what that mac address in your list was referring to. When creating names, you can make them as descriptive as necessary.
EDIT: Here's a function that takes a name as a string, looks up the associated IP from DNS, then pings. If DNS resolution fails or the ping doesn't report success, the function returns false. It returns true otherwise. You should also log the exceptions for troubleshooting later, BTW.
public bool Check(string Name)
{
//try dns resolution, if fails, quit reporting error
IPAddress[] addresses = null;
try
{
addresses = Dns.GetHostAddresses(Name);
}
catch (SocketException)
{
return false;
}
//ping remote address
PingReply reply = ping.Send(addresses[0]);
switch (reply.Status)
{
case IPStatus.Success:
return true;
break;
default:
return false;
break;
}
}
EDIT 2: Here are the namespaces I'm using in this project. Not sure what's where exactly, but adding these three will get everything going.
using System.Net.NetworkInformation;
using System.Net;
using System.Net.Sockets;
You need to use RARP http://en.wikipedia.org/wiki/Reverse_Address_Resolution_Protocol
and
MAC address to IP Address on Same LAN in C#
Depending on the network, you may be able to use the arp cache to look up the IP of a given MAC address (even if your network is set up such that you could do this, it will only work if the MAC address of the other machine is in the cache at the time of the request). You can read about arp on Wikipedia
If you have the MAC address you can get the IP address and machine name using MAC address. Once you have the IP you can simply ping the machine.
See this code for an example of how to get IP address from MAC address