Как я могу получить IP-адрес подключенного хоста из Windows Socket (C ++)?

Я видел этот вопрос раньше, но я так и не нашел ответа, который работал бы. Мне нужно получить явный IP-адрес (например, 123.456.789.100) и номер ПОРТА компьютера, к которому подключен мой сервер, чтобы пересылать эту информацию другим клиентам. Я использую WinSock2.h в Windows 7 (Home Premium), Visual Studio 2010 Professional - создание «консольного приложения C ++». Это TCP-соединение. Вот мой код:

sockaddr_in* addr = new sockaddr_in;
int addrsize = sizeof(addr);
getsockname(clientSock, (sockaddr*)addr, &addrsize);
char* ip = inet_ntoa(addr->sin_addr);
int port = addr->sin_port;
printf("IP: %s ... PORT:%d\n", ip, port);

Это всегда дает мне 205.205.205.205 для IP и 52685 для PORT каждый раз. Я пробовал альтернативы, в том числе gethostbyname, который работает, но мне нужен сам фактический IP. Я также пробовал getpeername () вместо getsockname (), но результаты были идентичными. Я нахожусь за маршрутизатором, но пока использую и сервер, и клиент на одном компьютере.

Заранее благодарим за любую помощь!


person Sefu    schedule 11.07.2011    source источник


Ответы (2)


getpeername () - это функция, которую вы хотите использовать.

Некоторые ошибки, которые я вижу в вашем коде:

1) Вы выделяете адрес в куче. В этом нет необходимости, просто объявите "sockaddr_in addr;" вместо этого в стеке и передайте & addr (вместо addr) вашему вызову getpeername ().

2) addrsize устанавливается равным размеру указателя (например, 4 или 8), а не размеру фактического sockaddr_in, что означает, что ...

3) getsockname (), вероятно, не работает, но вы этого не знаете, потому что

4) Вы не проверяете возвращаемое значение getsockname (), чтобы узнать, была ли ошибка, что означает, что

5) Результаты, которые вы видите, просто показывают вам, какие случайные данные мусора были в (* addr) до вызова getsockname () / getpeername (), потому что вызов завершился неудачно, не записав ничего в структуру addr.

6) О, еще одна вещь ... обязательно заключите ссылку на addr.sin_addr в вызов ntohl () и ссылку на addr.sin_port в вызове ntohs (), иначе вы получите их в большом формате. endian форма при работе на компьютере с прямым порядком байтов (читай: на базе Intel), а это не то, что вам нужно.

person Jeremy Friesner    schedule 11.07.2011
comment
Да, вы были правы, это вызывало ошибку, и я ее не проверял. Большое спасибо, ваше решение сработало. - person Sefu; 11.07.2011

Да, вы были правы, это вызывало ошибку, и я ее не проверял. Большое спасибо, ваше решение сработало. Последний код, который у меня сработал, был следующим:

sockaddr_in addr;
int addrsize = sizeof(addr);
int result = getpeername(clientSock, (sockaddr*) &addr, &addrsize);
printf("Result = %d\n", result);
char* ip = inet_ntoa(addr.sin_addr);
int port = addr.sin_port;
printf("IP: %s ... PORT: %d\n", ip, port);

И это дало мне правильные результаты. Я ценю вашу помощь. Спасибо!

person Sefu    schedule 11.07.2011