SFML community forums
Help => Network => Topic started by: TheMagicNumber on March 07, 2011, 10:17:17 pm
-
Whenever I call GetLocalAddress, I get the localhost IP (127.0.0.1), is this normal? :)
-
No it shouldn't, unless you have a weird network configuration.
What is your actual local network address?
-
It's 192.168.0.100.
-
Can you show a minimal code that reproduces this problem, just to be sure? :)
-
Alright, here:
#include <iostream>
#include <SFML/Network.hpp>
int main(int argc, char* argv) {
std::cout << sf::IpAddress::GetLocalAddress().ToString();
return 0;
}
Prints "127.0.0.1"
-
What is your OS?
-
Windows 7 x64
I see you noticed that error of yours, by the way. ;)
-
Everytime I post bullshit, I get caught before I edit my message :lol:
-
Any ideas? ipconfig gives me the correct information.
-
No idea. Maybe you can play with the function's code directly and see if anything's wrong.
-
All the stuff I found online that works used getaddrinfo() or gethostbyname().
-
Yes, there are other solutions. However getsockname on a local socket should be the best option, I'd like to understand why it fails on your machine (and not on any other Windows PC).
-
If the socket is using a connectionless protocol, the address may not be available until I/O occurs on the socket.
From: http://msdn.microsoft.com/en-us/library/ms738543(v=vs.85).aspx
Is this relevant? I would probably assume that the function would return SOCKET_ERROR, though.
-
Hum...
If the socket is using a connectionless protocol, the address may not be available until I/O occurs on the socket.
Can you try to add this, between connect and gethostname?
char buffer[] = {0};
send(socket, buffer, 1, 0);
You can copy the function into your code directly if you don't want to recompile SFML. If you do so, you'll have to do the following replacements:
- SocketHelper::SocketType --> SOCKET
- SocketHelper::InvalidSocket() --> INVALID_SOCKET
- SocketHelper::Close --> closesocket
-
Nope. :(
-
Doesn't work at all? Can you show me your code?
-
It gave the same result.
sf::IpAddress GetLocalAddress()
{
// The method here is to connect a UDP socket to anyone (here to localhost),
// and get the local socket address with the getsockname function.
// UDP connection will not send anything to the network, so this function won't cause any overhead.
sf::IpAddress localAddress;
// Create the socket
SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
return localAddress;
// Connect the socket to localhost on any port
sockaddr_in address = CreateAddress(INADDR_LOOPBACK, 0);
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
closesocket(sock);
return localAddress;
}
char buffer[] = {0};
send(sock, buffer, 1, 0);
// Get the local address of the socket connection
int size = sizeof(address);
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
{
closesocket(sock);
return localAddress;
}
// Close the socket
closesocket(sock);
// Finally build the IP address
localAddress = sf::IpAddress(ntohl(address.sin_addr.s_addr));
return localAddress;
}
-
Ok... last try: check the return value of send, just to be sure (compare it against SOCKET_ERROR).
-
Done, it didn't return SOCKET_ERROR.
-
Can you add WSA initialization to your own code?
WSADATA init;
WSAStartup(MAKEWORD(2, 2), &init);
-
Just put that at the beginning of main() and ran, same result. D:
I'll be back later.
-
I've run out of ideas :D
-
:?
-
I am having this same issue at home (using 2.0), and I've dealt with PC's with multiple IP address' in the past. I didn't have time to debug it, but I'll look at it tonight and get back to you here.
I do think the API should be modified since often PC's are on multiple networks. In fact, the PC I use at work has 3 IP address' to 3 different networks. For an simple test app I wrote, I included this bit of code (Windows only) to select which IP address to use (see below).
I would love for the GetLocalIpAddress to maybe pass an index, so we can get all the possible local IP addresses, or some other method of getting all the IP addresses the PC has.
Thanks.
/* retreive our IP address */
{
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
pIPAddrTable = (MIB_IPADDRTABLE*) malloc( sizeof( MIB_IPADDRTABLE) );
/* Make an initial call to GetIpAddrTable to get the
necessary size into the dwSize variable */
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
{
free( pIPAddrTable );
pIPAddrTable = (MIB_IPADDRTABLE *) malloc ( dwSize );
}
/* Make a second call to GetIpAddrTable to get the
actual data we want */
GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
/* fill in our addrs */
for (i = 0; i < pIPAddrTable->dwNumEntries; i++)
{
if ((pIPAddrTable->table[i].dwAddr != 0) &&
(pIPAddrTable->table[i].dwAddr != LOCALHOST))
{
addr[NumAddrs].s_addr = pIPAddrTable->table[i].dwAddr;
NumAddrs++;
}
}
}
/* ask users which IP address to use if more than one */
while ((NumAddrs > 1) && bContinue)
{
C8 c8Char;
printf("Choose Which IP address to listen on:\n");
for (i = 0; i < NumAddrs; i++)
{
printf("%d: IP %d.%d.%d.%d\n", i+1, PRINT_IP(addr[i].s_addr));
}
c8Char = getch() - '0';
if ((c8Char > 0) && (c8Char < NumAddrs+1))
{
bContinue = FALSE;
gu32IpIndex = c8Char-1;
printf("------------------------------\n");
}
}
-
I am having this same issue at home (using 2.0), and I've dealt with PC's with multiple IP address' in the past. I didn't have time to debug it, but I'll look at it tonight and get back to you here.
I do think the API should be modified since often PC's are on multiple networks. In fact, the PC I use at work has 3 IP address' to 3 different networks. For an simple test app I wrote, I included this bit of code (Windows only) to select which IP address to use (see below).
I would love for the GetLocalIpAddress to maybe pass an index, so we can get all the possible local IP addresses, or some other method of getting all the IP addresses the PC has.
Thanks.
So, I tried to create a solution to this in my app by checking if the GetLocalAddress() was LOCALHOST, and, instead creating an sf::IpAddress with my real IP address (using code close to that above). However, using that code doesn't seem to allow me to send any packets out the ethernet interface I'm trying to use. Checking Wireshark, there's no data being sent on my ethernet interface (using UdpSocket here).
So, until sf:Network is modified to properly handle this situation (perhaps you need to modify Bind() to include the IP address to Bind the socket to as well as port assuming there will be multiple possible network interfaces), I'm going to implement my solution in good old sockets.