I tried to search for it but I could'nt find any working soultions.
Nowadays Windows can detect more than ONE PROPER HARDWARE installed eternet controlled due to Hamachi, Virtual box etc etc.
Now i need to get the real IP adress of machine. When i tried do it by using gethostbyname it returned IP adress of my Hamachi client.
Now I need to find 100% solid method to receive real ip adress. Any links/tips/articles/methods really appreciate.
EDIT:
So far got this - method sugested by Remy Lebau, but it doesn't work the way I want - always returning 127.0.0.1:
int main()
{
WSADATA WSA_info;
if (WSAStartup(MAKEWORD(2,2),&WSA_info)!=0)
{
std::cout << "Error with WSA.\n";
std::cin.get();
return -1;
}
SOCKADDR_IN adress;
adress.sin_family = AF_INET;
adress.sin_port = htons(80);
adress.sin_addr.S_un.S_addr = inet_addr("213.241.88.40"); //its google's IP adress - to chech it I used ping google.com in cmd (maybe there is somethign wrong with this)
SOCKET sock;
if ((sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))== INVALID_SOCKET){
std::cout << "Error while creating socket." << std::endl;
closesocket(sock);
WSACleanup();
std::cin.get();
return -1;
}
if (connect(sock,(sockaddr*)&adress,sizeof(sockaddr))== SOCKET_ERROR) {
std::cout << "Couldnt connect." << std::endl;
closesocket(sock);
WSACleanup();
std::cin.get();
return -1;
}
sockaddr_in test;
int len = sizeof(test);
getsockname(sock,(struct sockaddr *) &test, &len);
std::cout << inet_ntoa(test.sin_addr);
std::cin.get();
}
A PC can be connected to multiple networks at the same time (Internet, VM, VPN, etc), each with its own IP address, and you could initialize sockets on any of them at the same time and it would work. And more and more common, PCs are getting their Internet access from home router/ICS connections, not directly from Internet modems.
So what "real IP address" are you looking for? The PC can have multiple IP addresses, and they are all "real" as far as the OS cares.
If you just want to enumerate the available local IP addresses, you can use GetAdaptersInfo() or GetAdaptersAddresses(). DO NOT use gethostbyname() to discover local IP addresses - that is not what it is meant for, and it can report false information!
I think the question you actually want to ask is - how do I find the IP of the Ethernet controller used to access the Internet - am I right?
For that, you will have to connect() an unbound socket to an outside server that is running on the Internet, and if successful then you can use getsockname() to find out which local IP address the OS bound the socket to, for example:
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in remoteaddr = {0};
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = inet_addr("remote ip address");
remoteaddr.sin_port = htons(80);
if (connect(sock, (sock_addr*)&remoteaddr, sizeof(remoteaddr)) == 0)
{
sockaddr_in localaddr = {0};
int len = sizeof(localaddr);
getsockname(sock, (sock_addr*)&localaddr, &len);
// use localaddr as needed...
}
closesocket(sock);
But that is only going to tell you the IP address on the local PC. If you are behind a router/ICS, that is not going to be the same IP address that the Internet uses to send packets to your PC. To get that IP address, you can connect to and query an outside iplookup service, such as http://whatismyip.com, and see what IP address it reports back to you.
Related
I want to get the IP address of the computer my program is launched on, to be able then to send it to a client, but I always get 0.0.0.1 instead of the real IP address (like 127.0.0.1 for instance).
I'm currently able to get the port, but not the IP address.
How can I get it?
The best solution would be to be able to get it with a sockaddr_in. Here's what I'm currently doing:
int open_connection(char* ip, int* port)
{
int sock;
struct sockaddr_in sin;
socklen_t len;
int i;
i = 0;
len = sizeof(sin);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return (-1);
bzero(&sin, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0)
perror("Error on bind");
if (getsockname(sock, (struct sockaddr *)&sin, &len) != 0)
perror("Error on getsockname");
strcpy(ip, inet_ntoa(sin.sin_addr)); // IP = 0.0.0.0
*port = sin.sin_port;
return (sock);
}
EDIT: I understand I was going on the wrong way with my way of thinking. So my question is: What's the best way to get your own IP address?
When you bind() a socket to 0.0.0.0, that is the only IP the socket has available when calling getsockname(). It means the socket is bound to all local interfaces. In order to get a specific IP from a socket, it has to be bound to a specific IP.
Using the socket API to get the machine's local IP(s) is the wrong approach anyway. A common mistake is to use gethostname() with gethostbyname() or getaddrinfo() to get the local IP list. Usually that works, but it has some hidden gotchas that can cause false information, but people tend to ignore that fact, or don't even know about it in the first place (I didn't know about it for years, but then I learned better).
Instead, you really should use platform-specific APIs for enumerating the local networking interfaces. That will provide more reliable information. Windows has GetAdaptersInfo() and GetAdaptersAddresses(). Other platforms have getifaddrs(). Those will tell you what local IPs are available. You can then bind() a socket to 0.0.0.0 in order to accept clients on any of those IPs, or bind() to a specific IP to accept clients only on that IP.
The sockets API allows you to enumerate the IP addresses assigned to your network interfaces, but it will not tell you what you "real IP" is if you are connecting to the Internet from behind a router.
The only way to know it is by asking someone outside. Thats how servers like FileZilla FTP Server do that. They instruct you to configure the URL to a "ip.php" script like this one in the server's settings so it can ask the Internet whats its public IP address, to use in Passive Mode.
You can also consider using STUN, a protocol widely used in VoIP to discover public IP.
You could call ioctl(sock, SIOCGIFADDR, adr)
see netdevice(7)
Following #Remy Lebeau's answer I wrote a function that return current machine's address. I have only tested this on macOS High Sierra.
interfaec can be anything among lo0, en0, etc.
ipVersion can be AF_INET or AF_INET6.
long int getInternalAddress(char* interface, sa_family_t ipVersion)
{
struct ifaddrs *ifaddrHead, *ifaddr;
/* int_8 */
sa_family_t family;
int n;
char *interfaceName;
if (getifaddrs(&ifaddrHead) != 0)
{
fprintf(stderr, "ifaddrs error");
}
/* iterate through address list */
for (ifaddr = ifaddrHead, n = 0; ifaddr != NULL; ifaddr = ifaddr->ifa_next, n++)
{
family = ifaddr->ifa_addr->sa_family;
interfaceName = ifaddr->ifa_name;
if (!family || family != ipVersion || strcmp(interfaceName, interface)) continue;
struct sockaddr *addr = ifaddr->ifa_addr;
struct sockaddr_in* addr_in = (struct sockaddr_in*) addr;
long int address = addr_in->sin_addr.s_addr;
freeifaddrs(ifaddrHead);
return address;
}
freeifaddrs(ifaddrHead);
return 0;
}
To use it,
int main()
{
long int address = getInternalAddress((char*) &"en0", AF_INET);
printf("%li\n", address);
return 0;
}
I'm still a beginner in C, if there is anything wrong please tell me.
Rewritten to try and be clear on what I need.
My goal is to duplicate the function of a device made by Digital Yacht in an embedded Intel Edison processor running C and Linux. The device sends via UDP to phone apps such as iRegatta and others. To set up the app, only the port number is entered. No ip address is entered in UDP mode on the app. I thought this was trivial but the experts here so far have said it is impossible so it must not be trivial. Perhaps that is why with all my hours of reading I cannot find an example. I am being voted down because, I am told, that what I am trying to do it impossible but it is not as it is done. I don't know how it is done, which is why I came to experts here.
I want to send nmea messages that might look like this:
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
and I want any number of random Android phones to be able to receive them with the appropriate app. There are many apps that can be set up to receive UDP data where you just specify a port number. There is no ip address involved in the setup of the apps. Also, I do not wish to receive anything from the Android phones. This is one way and no ability to re-transmit so if a message does not get there, it has another chance next time. Everything is updated once a second.
I tried the following and I do not get data in the app. From the comments, I must need to add some kind of router function in my Linux machine.
void init_udp(){
return;
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0){
printf("ER UDP Socket error\n");
}
else printf("UP Socket %d OK\n",sock);
}
void write_udp(char *buf){
return;
// nmea data is in buff
if (sock >= 0){
int on = 1;
setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on) );
struct sockaddr_in address = {0};
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr( "255.255.255.255" ); //
address.sin_port = htons( 3000 );
if ( sendto( sock, buf, strlen(buf), 0, (struct sockaddr*)&address, sizeof(address) ) < 0) printf("ER UDP send error\n");
else {
printf("UP %s\n",buf);
}
}
}
I am not really sure what I need to do.
What you want to do is send a UDP packet to a broadcast IP address. This will send to thing in the subnet.
eg 10.255.255.255 is the broadcast address for the 10.x.x.x subnet. You can also use the global 255.255.255.255 which should also send to your subnet and no router is going to pass that on to another one these days.
Also you need to make your socket able to send broadcast messages. In particular you need the option SO_BROADCAST set. The following is specifically Windows because of the BOOL. Its presumably an int for most platforms.
BOOL on = TRUE;
setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on) );
Also you can't use send() for a UDP socket unless its "connected", so you should use sendto() and use the broadcast address.
To specify an address and port, use need to create a socket address.
struct sockaddr_in address = {0};
address.sin_family = AF_INET;
address.sin_add.s_addr = inet_addr( "255.255.255.255" );
address.sin_port = htons( 3000 );
sendto( sock, buff, strlen(buff), 0, (struct sockaddr*)&address, sizeof(address) );
Note the use of the typecast. This is because sendto takes a sockaddr which is a generic address type, and here we are using an IPV4 address specifically. The sockaddr_in maps onto the sockaddr
I want to get the IP address of the computer my program is launched on, to be able then to send it to a client, but I always get 0.0.0.1 instead of the real IP address (like 127.0.0.1 for instance).
I'm currently able to get the port, but not the IP address.
How can I get it?
The best solution would be to be able to get it with a sockaddr_in. Here's what I'm currently doing:
int open_connection(char* ip, int* port)
{
int sock;
struct sockaddr_in sin;
socklen_t len;
int i;
i = 0;
len = sizeof(sin);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return (-1);
bzero(&sin, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0)
perror("Error on bind");
if (getsockname(sock, (struct sockaddr *)&sin, &len) != 0)
perror("Error on getsockname");
strcpy(ip, inet_ntoa(sin.sin_addr)); // IP = 0.0.0.0
*port = sin.sin_port;
return (sock);
}
EDIT: I understand I was going on the wrong way with my way of thinking. So my question is: What's the best way to get your own IP address?
When you bind() a socket to 0.0.0.0, that is the only IP the socket has available when calling getsockname(). It means the socket is bound to all local interfaces. In order to get a specific IP from a socket, it has to be bound to a specific IP.
Using the socket API to get the machine's local IP(s) is the wrong approach anyway. A common mistake is to use gethostname() with gethostbyname() or getaddrinfo() to get the local IP list. Usually that works, but it has some hidden gotchas that can cause false information, but people tend to ignore that fact, or don't even know about it in the first place (I didn't know about it for years, but then I learned better).
Instead, you really should use platform-specific APIs for enumerating the local networking interfaces. That will provide more reliable information. Windows has GetAdaptersInfo() and GetAdaptersAddresses(). Other platforms have getifaddrs(). Those will tell you what local IPs are available. You can then bind() a socket to 0.0.0.0 in order to accept clients on any of those IPs, or bind() to a specific IP to accept clients only on that IP.
The sockets API allows you to enumerate the IP addresses assigned to your network interfaces, but it will not tell you what you "real IP" is if you are connecting to the Internet from behind a router.
The only way to know it is by asking someone outside. Thats how servers like FileZilla FTP Server do that. They instruct you to configure the URL to a "ip.php" script like this one in the server's settings so it can ask the Internet whats its public IP address, to use in Passive Mode.
You can also consider using STUN, a protocol widely used in VoIP to discover public IP.
You could call ioctl(sock, SIOCGIFADDR, adr)
see netdevice(7)
Following #Remy Lebeau's answer I wrote a function that return current machine's address. I have only tested this on macOS High Sierra.
interfaec can be anything among lo0, en0, etc.
ipVersion can be AF_INET or AF_INET6.
long int getInternalAddress(char* interface, sa_family_t ipVersion)
{
struct ifaddrs *ifaddrHead, *ifaddr;
/* int_8 */
sa_family_t family;
int n;
char *interfaceName;
if (getifaddrs(&ifaddrHead) != 0)
{
fprintf(stderr, "ifaddrs error");
}
/* iterate through address list */
for (ifaddr = ifaddrHead, n = 0; ifaddr != NULL; ifaddr = ifaddr->ifa_next, n++)
{
family = ifaddr->ifa_addr->sa_family;
interfaceName = ifaddr->ifa_name;
if (!family || family != ipVersion || strcmp(interfaceName, interface)) continue;
struct sockaddr *addr = ifaddr->ifa_addr;
struct sockaddr_in* addr_in = (struct sockaddr_in*) addr;
long int address = addr_in->sin_addr.s_addr;
freeifaddrs(ifaddrHead);
return address;
}
freeifaddrs(ifaddrHead);
return 0;
}
To use it,
int main()
{
long int address = getInternalAddress((char*) &"en0", AF_INET);
printf("%li\n", address);
return 0;
}
I'm still a beginner in C, if there is anything wrong please tell me.
Since there is no function in BSD sockets to get the IP address, I did client/server program to establish the connection. One thread for each: server and client.
The IP address returned from "inet_ntoa" with localhost was 127.0.0.1.
But the network says my computer is this 10.0.0.7, and this address is what works.
How do I get the 10.0.0.7 address?
Thx
Here is my code:
DWORD WINAPI CIpAddressDlg::Thread_TcpServer(LPVOID iValue)
{
CIpAddressDlg *pp = (CIpAddressDlg*)iValue;
CString c;
char buffer[128];
int sinlen;
struct sockaddr_in sin;
int s, h;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(4000); // Port
s = socket(AF_INET, SOCK_STREAM,0);
bind(s,(struct sockaddr*)&sin,sizeof(sin));
listen(s,1);
sinlen = sizeof(sin);
h=accept(s,(struct sockaddr*)&sin,&sinlen );
//get IP address
int len = sizeof sin;
if(::getsockname(h,(struct sockaddr*)&sin,&len) == -1)
pp->MessageBox("Error local host ip");
c.Format("%d\nlocal addr %s:%u\n errno: %d", sin.sin_addr, inet_ntoa(sin.sin_addr),ntohs(sin.sin_port), errno);
pp->MessageBox(c);
//verification of send
recv(h,buffer,sizeof(buffer),0);
pp->MessageBox(buffer);
send(h,buffer,strlen(buffer),0);
::closesocket(s);
return 0;
}
DWORD WINAPI CIpAddressDlg::Thread_TcpClient(LPVOID iValue)
{
CIpAddressDlg *pp = (CIpAddressDlg*)iValue;
CString c;
char buffer[128]= "Hello world";
struct sockaddr_in sin;
struct hostent *host;
int s;
host = gethostbyname("localhost");
memcpy(&(sin.sin_addr), host->h_addr,host->h_length);
sin.sin_family = host->h_addrtype;
sin.sin_port = htons(4000);
s = socket(AF_INET, SOCK_STREAM,0);
connect(s, (struct sockaddr*)&sin,sizeof(sin));
send(s,buffer,strlen(buffer)+1,0);
recv(s,buffer,sizeof(buffer),0);
::closesocket(s);
return 0;
}
Despite the intuitive appeal of the concept and, for that matter, widespread belief in said concept, computers do not have IP addresses.
Interfaces have IP addresses.
You can get a list of the interfaces and choose the first one. Unfortunately, getting a list of interfaces in most languages is system dependent.
The usual approach is to just use 0.0.0.0.
There are easier ways to get the "private" / "LAN" IP of the machine your program is running on. Your solution is very ingenuitive though.
I think the most straightforward is probably GetAdaptersAddresses. The example code on the MSDN page seems pretty thorough.
But if that requires a newer compiler version, consider GetAdaptersInfo. See "Method Three" here and some sample code here.
Also, it seems like you could also access the IP address via the WinSock API. See this example.
Lastly, just as a sidenote, there is a function in BSD sockets to do exactly this (getifaddrs()), its just not ported to Windows.
I'm having trouble figuring this out - I'm working with sockets in C using this guide - http://binarii.com/files/papers/c_sockets.txt
I'm trying to automatically get my ip and port using:
server.sin_port = 0; /* bind() will choose a random port*/
server.sin_addr.s_addr = INADDR_ANY; /* puts server's IP automatically */
...
...
bind(int fd, struct sockaddr *my_addr,int addrlen); // Bind function
After a successful bind, how do I find out what IP and Port I'm actually assigned?
If it's a server socket, you should call listen() on your socket, and then getsockname() to find the port number on which it is listening:
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (getsockname(sock, (struct sockaddr *)&sin, &len) == -1)
perror("getsockname");
else
printf("port number %d\n", ntohs(sin.sin_port));
As for the IP address, if you use INADDR_ANY then the server socket can accept connections to any of the machine's IP addresses and the server socket itself does not have a specific IP address. For example if your machine has two IP addresses then you might get two incoming connections on this server socket, each with a different local IP address. You can use getsockname() on the socket for a specific connection (which you get from accept()) in order to find out which local IP address is being used on that connection.
The comment in your code is wrong. INADDR_ANY doesn't put server's IP automatically'. It essentially puts 0.0.0.0, for the reasons explained in mark4o's answer.