How to get your public ip address using Qt c++ - c++

I'm writing a gui for an net address etc. calculator. All the coding is done but now i want to have a button that will get your computer's ip address. I was looking for a solution and saw various posts on stackoverflow but none of them work for me...
Edit: this piece of code worked for me
QTcpSocket socket;
socket.connectToHost("8.8.8.8", 53);
if (socket.waitForConnected()) {
QString text = socket.localAddress().toString();
ui->ipAddress->setText(text);
} else {
QMessageBox msg;
msg.setText("Couldn't connect to the DNS server! No internet connection...");
msg.setWindowTitle("No internet connection");
msg.setIcon(QMessageBox::Critical);
msg.exec();
}```

I think the class you are looking for is the QNetworkInterface class.
From the man page:
The QNetworkInterface class provides a listing of the host's IP
addresses and network interfaces.
For example, calling QNetworkInterface::allAddresses() is a quick way to get a list of all the IP addresses on your machine. As for which one is the "public IP address", that's not a well-defined concept. On most modern consumer setups, it's arguable that there is no public IP address, as consumer PCs are typically hidden behind a NAT layer, and as such the only public IP address is on the network router, not on the user's computer itself.

You can use QHostInfo for this purpose. Ex;
auto list = QHostInfo::fromName(QHostInfo::localHostName()).addresses();

I am using following code snippet in my current project to get ip address. And it is working fine both on Desktop Linux and Embedded Linux. device is network interface name like "wlan0", "eth0" etc. It returns QNetworkAddressEntry which contains both ip and netmask. Use ip() function get ip address. Usually the first address entry is non-virtual one, so that's why am getting the first one.
const QNetworkInterface& networkInterface = QNetworkInterface::interfaceFromName(device);
if (networkInterface.isValid())
{
const QList<QNetworkAddressEntry>& addressEntries = networkInterface.addressEntries();
if (!addressEntries.isEmpty())
return addressEntries.front();
}
return QNetworkAddressEntry(); // could not found, invalid adress entry
Don't forget to add QT += network to your pro file.

Using QNetworkAccessManager, you can tap this free REST api: https://www.ipify.org/
That supports various options, such as returning the results in json. If you simply get that url, it will respond with the ip address you are most likely hoping to get back, in a raw format (i.e. a naked string).

Related

Cannot set LinkLocalAddressBehavior to LinkLocalAlwaysOff

I'm trying to set LinkLocalAddressBehavior for an interface to LinkLocalAlwaysOff by using SetIpInterfaceEntry function, but I'm always getting ERROR_INVALID_PARAMETER. When I set LinkLocalAddressBehavior to LinkLocalDelayed, SetIpInterfaceEntry executes without problem.
I haven't found anything that may help with this problem at MSDN (SetIpInterfaceEntry, MIB_IPINTERFACE_ROW or NL_LINK_LOCAL_ADDRESS_BEHAVIOR).
Any suggestions?
Thanks!
UPDATE: Code sample:
// Initialize MIB_IPINTERFACE_ROW with actual InterfaceLuid:
auto row = MIB_IPINTERFACE_ROW{ AF_INET, 1689399632855040 };
// GetIpInterfaceEntry succeeds
auto result = GetIpInterfaceEntry(&row);
// Setting the value:
row.LinkLocalAddressBehavior = LinkLocalAlwaysOff;
// SetIpInterfaceEntry fails with ERROR_INVALID_PARAMETER:
result = SetIpInterfaceEntry(&row);
According to this article:
The assignment of an IPv4 Link-Local address on an interface is based
solely on the state of the interface, and is independent of any other
protocols such as DHCP. A host MUST NOT alter its behavior and use of
other protocols such as DHCP because the host has assigned an IPv4
Link-Local address to an interface.
So we are not able to change its behavior, when it is enabled. the LinkLocalDelayed succeed because the original status was LinkLocalDelayed.
For IPv6, I found an answer on msdn. Seem like they have some similar behaviors. If one has been enable, then it will not be able to disabled.

How to get local ip address in network that I'm currently connected to?

I know I can use QNetworkInterface::allAddresses(), but this returns me also many IPs I don't need at all, for example virtual networks.
And I can't connectToHost() and check localAddress() of socket, my program will be used in networks separated from internet, so I won't be able to connect to Google DNS / anything reliable.
Is there any way to filter address from list allAddresses(), or is there other Qt function I could use?
This should do the job:
auto allNetworkAddresses = QNetworkInterface::allAddresses();
for (const auto& address : allNetworkAddresses)
{
if (address.protocol() == QAbstractSocket::IPv4Protocol &&
address != QHostAddress(QHostAddress::LocalHost))
{
//use adress in any way needed
}
}

find list of all accessible hostnames

I have an application where a user can dynamically configure TCP connections between remote processes. I'd like to make sure the user input is valid, by providing them with a QComboBox that is pre-populated with all the valid hostnames on their network. Is there a way to find the list of hostnames using Qt?
If possible I'd like to do this on both windows and linux.
This can be achieved using Qt classes, but you'll also need to use system tools to gather the hostname information, and those tools are different between linux and windows. That said, with a simple preprocessor switch, we can use QProcess to call the right one, and pull the hostnames out of the result using a QRegExp:
// find valid hostnames
QStringList hostnames;
QRegExp hostnameRx("\\\\\\\\(.*)");
QProcess cmd(this);
#ifdef _WIN32
cmd.start("cmd.exe");
cmd.write("net view\r\n");
cmd.write("exit\r\n");
#else
cmd.start("smbtree", QStringList() << "--no-pass");
#endif // _WIN32
cmd.waitForFinished();
while (!cmd.atEnd())
{
QString line = cmd.readLine();
hostnameRx.indexIn(line);
if (!hostnameRx.cap(1).trimmed().isEmpty())
{
hostnames << hostnameRx.cap(1).trimmed();
}
}
The regex strips the begining '\\' returned by both net view and smbtree, because QTcpSocket connections take hostnames without it.
Obviously, the QStringListcan be used to populate a QComboBox:
QComboBox* box = new QComboBox(this);
box->insertItems(0, hostnames);
NOTE: net view and smbtree are only going to show computers with accessible shares. You can try nmap for a more complete list of live hosts, but you're going to need to run as root and you'll still probably hit a lot of firewall issues.

How to check if you have live internet connection programmatically using C++

How can I check if I have a internet connection or live internet connection using C++?
C++ has no builtin functions for this, you will need to resort to system APIs. An easiest and obvious way is to create a socket and try to connect it to some known IP or check if DNS is working.
Some useful links:
http://msdn.microsoft.com/en-us/library/ms740673(VS.85).aspx (Windows Sockets)
http://www.tenouk.com/cnlinuxsockettutorials.html (Linux/Unix sockets)
The easiest way is to try to connect to a known outside IP address. If it fails in Windows, the connect function will return SOCKET_ERROR, and WSAGetLastError will usually return WSAEHOSTUNREACH (meaning the packet couldn't be sent to the host). In Linux, you'll get back a -1, and errno will be ENETUNREACH.
For starters you can subscribe to the ISensIntf to check if you have a valid network connection. (Let me know if you need help in this. Its painful to register for the events etc.).
After that, you can use Api's like IsNetworkAlive, InternetGetConnectedStateEx or the InternetCheckConnection to check connectivity to the internet etc.
If your using C# or VB, then first Add a reference to
Microsoft.VisualBasic.Code.
Microsoft.VisualBasic.Devices.Network network = new Microsoft.VisualBasic.Devices.Network();
network.NetworkAvailabilityChanged += new Microsoft.VisualBasic.Devices.NetworkAvailableEventHandler(network_NetworkAvailabilityChanged);
...
private static void network_NetworkAvailabilityChanged(object sender, Microsoft.VisualBasic.Devices.NetworkAvailableEventArgs e)
{
if (e.IsNetworkAvailable)
{
//network is connected.. do something..
}
else
{
//network isnt connected.. do something else.
}
Hope this helps

Determining the network connection link speed

How do I programmatically determine the network connection link speed for an active network connection - like Task Manager shows you in the Networking tab? I'm not really after the bandwidth available, just a figure for the current connection, e.g. 54Mbps, 100Mbps etc.
Win32_NetworkAdapter WMI class can help you (Speed property). It returns the value 54000000 for my WiFi adapter connected to a WiFi-g access point.
In the end I found the Win32_PerfRawData_Tcpip_NetworkInterface WMI class, as I need to support legacy platforms which, unfortunately, the Win32_NetworkAdapter doesn't do. Win32_PerfRawData_Tcpip_NetworkInterface has a CurrentBandwidth property which gives me what I need on all required platforms (I realise I said I didn't need "bandwidth" but its acceptable and appears to return the "nominal bandwidth" of the adapter anyway).
Thanks to all those who posted, pointing me in the right direction.
.NET way how to know adapter speed is
IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
if ( nics != null )
for (int i = 0; i < nics.Length; i++)
Console.WriteLine("Adapter '{0}' speed : {1}", nics[i].Name, nics[i].Speed);
Some adapters are tunnels, so their speed will be returned as 0.
Read NetworkInterface documentation on the MSDN for more information.