Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.118.145.114] |
|
Сообщ.
#1
,
|
|
|
Как определить, что два ip адреса находятся в одной подсети на c++?
Дано: 1. ipv4 адрес компьютера_1 2. ipv4 адрес компьютера_2 3. ipv4 маска подсети CStringA get_ipv4_submask(/*/Нужные параметры/*/) { /*/ /*/ return CStringA("255.255.255.255") } bool are_ipv4_from_one_subnet(CStringA parameter_computer_1_ipv4,CStringA parameter_computer_2_ipv4,CStringA parameter_mask_ipv4) { /*/ /*/ return false; } Помогите дописать функции. Добавлено Нашёл на сайте Майкрософт: #include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> #include <stdio.h> #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "ws2_32.lib") #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) /* Note: could also use malloc() and free() */ int __cdecl main() { int i; /* Variables used by GetIpAddrTable */ PMIB_IPADDRTABLE pIPAddrTable; DWORD dwSize = 0; DWORD dwRetVal = 0; IN_ADDR IPAddr; /* Variables used to return error message */ LPVOID lpMsgBuf; // Before calling AddIPAddress we use GetIpAddrTable to get // an adapter to which we can add the IP. pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE)); if (pIPAddrTable) { // 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); } if (pIPAddrTable == NULL) { printf("Memory allocation failed for GetIpAddrTable\n"); exit(1); } } // Make a second call to GetIpAddrTable to get the // actual data we want if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) != NO_ERROR ) { printf("GetIpAddrTable failed with error %d\n", dwRetVal); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL)) { printf("\tError: %s", lpMsgBuf); LocalFree(lpMsgBuf); } exit(1); } printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; printf("\tBroadCast[%d]: \t%s (%ld%)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); printf("\tType and State[%d]:", i); if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY) printf("\tPrimary IP Address"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC) printf("\tDynamic IP Address"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED) printf("\tAddress is on disconnected interface"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED) printf("\tAddress is being deleted"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT) printf("\tTransient address"); printf("\n"); } if (pIPAddrTable) { FREE(pIPAddrTable); pIPAddrTable = NULL; } exit(0); } |
Сообщ.
#2
,
|
|
|
Цитата Kozlov_Sergey @ Помогите дописать функции. Разобравшись в теории, сам напишешь без напрягов. 1) Адреса и маску - переводишь в 4-байтовое беззнаковое целое 2) Адрес1 побитовое "и" Маска - дадут подсеть первого адреса 3) Адрес2 побитовое "и" Маска - дадут подсеть второго адреса 4) Сравнить полученные подсети из п.2 и п.3 - если равны, то в одной подсети, иначе в разных |
Сообщ.
#3
,
|
|
|
Сейчас стоит задача определить маску по ipv4 и каким-то ещё параметрам в общем случае (не для текущего компьютера).
|
Сообщ.
#4
,
|
|
|
Цитата Kozlov_Sergey @ Сейчас стоит задача определить маску по ipv4 и каким-то ещё параметрам в общем случае (не для текущего компьютера). Маска по адресу не определяется (есть ряд предопределенных адресов, со своими масками, это отдельный вопрос). Но в общем случае - маска по адресу не определяется, она задается настройками. Посему, уточнение некорректно. |
Сообщ.
#5
,
|
|
|
Пусть Junior Developer переделает код с функцией main в код с прототипами, пока я схожу за пиццей.
А то я уже хочу работу раздавать и получать готовое для использования в больших целях. |
Сообщ.
#6
,
|
|
|
Цитата Kozlov_Sergey @ Пусть Junior Developer переделает код с функцией main в код с прототипами, пока я схожу за пиццей. А то я уже хочу работу раздавать и получать готовое для использования в больших целях. Кроме желания поесть питцы, ниче не понял. Приведенный выше код - чисто виндовое решение получения настроек сетевых интерфейсов локальной машины, на сколько я понял. К сетевому стандарту TCP/IP это отношения не имеет. Добавлено ADD: Если нужно работать чисто с виндовыми хостами - там вроде есть свои заморочки, типа утилиты netsh. Она позволяет работать с настройками удаленных windows-хостов. Но, это частный случай. Для *nix хостов - такое не прокатит. |
Сообщ.
#7
,
|
|
|
Переделайте мне пример для Windows для работы с локальными адресами в функции прототипы, которых я описал.
А то я устал и не могу думать сейчас. Потому что не сплю ночами по несколько часов. Вроде бы это не сложно. И желательно использовать операторы new и delete вместо кучи. А я вам каких исходников сетевых хороших скину. И вопрос в помощь тому, кто будет переделывать: "Напишите преобразование строки с ipv4 адресом в число DWORD". |
Сообщ.
#8
,
|
|
|
Цитата Kozlov_Sergey @ Переделайте мне пример для Windows для работы с локальными адресами в функции прототипы, которых я описал. Сергей, тут обычно "сделайте мне" выполняют за вознаграждение в разделе "Помощь студентам". Просто так делают, если есть собственный интерес. А если его нет, то увы, нет - делай самостоятельно. В процессе беседы вопрос стал понятен - для винды, короче, используя Win API. Гугли и ищи самостоятельно. Две наводочки: 1) WMI 2) CIMV2 Несложное гугление приведет тебя к куче примеров. Часть из которых (типа IPHlpAPI.dll) может быть удобной, но недокументированной. Часть типа WMI - громоздкой, но стандартной (документированной). На этом все, мне дальше не интересно. Пример на васике, по использованию WMI (установка сетевых параметров): strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colNetAdapters = objWMIService.ExecQuery _ ("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled=True") strIPAddress = Array("192.168.1.0") strSubnetMask = Array("255.255.255.0") For Each objNetAdapter in colNetAdapters errEnable = objNetAdapter.EnableStatic(strIPAddress, strSubnetMask) Next Надеюсь после питцы ты воспрянешь духом, нагуглишь док и осилишь |
Сообщ.
#9
,
|
|
|
Я уже начал переделывать функцию main с Майкрософтовского примера.
Тут, получается, только я Junior, и поэтому приходится переделывать всякую бяку, которая выпала из интернета. Я думал, что всем это надо. Добавлено Переделал. Вот исходник: #include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> #include <stdio.h> #include <string> #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "ws2_32.lib") #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) /* Note: could also use malloc() and free() */ bool get_ipv4_and_mask(std::string &result) { int i; /* Variables used by GetIpAddrTable */ PMIB_IPADDRTABLE pIPAddrTable; DWORD dwSize = 0; DWORD dwRetVal = 0; IN_ADDR IPAddr; /* Variables used to return error message */ LPVOID lpMsgBuf; // Before calling AddIPAddress we use GetIpAddrTable to get // an adapter to which we can add the IP. pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE)); if (pIPAddrTable) { // 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); } if (pIPAddrTable == NULL) { // printf("Memory allocation failed for GetIpAddrTable\n"); return false; } } // Make a second call to GetIpAddrTable to get the // actual data we want if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) != NO_ERROR ) { // printf("GetIpAddrTable failed with error %d\n", dwRetVal); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL)) { // printf("\tError: %s", lpMsgBuf); LocalFree(lpMsgBuf); } return false; } //printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { //printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; //printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); result += inet_ntoa(IPAddr); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; //printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); result += std::string("/"); result += inet_ntoa(IPAddr); result += std::string("\n"); //IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; /*/ printf("\tBroadCast[%d]: \t%s (%ld%)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); printf("\tType and State[%d]:", i); if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY) printf("\tPrimary IP Address"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC) printf("\tDynamic IP Address"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED) printf("\tAddress is on disconnected interface"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED) printf("\tAddress is being deleted"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT) printf("\tTransient address"); printf("\n"); /*/ } if (pIPAddrTable) { FREE(pIPAddrTable); pIPAddrTable = NULL; } return true; } Вот пример использования: std::string local_result; if(get_ipv4_and_mask(local_result)) { ::MessageBoxA(NULL, local_result.c_str(), "Information", MB_ICONINFORMATION); } Добавлено Мясо с минералкой и диван помогли. |
Сообщ.
#10
,
|
|
|
Цитата Kozlov_Sergey @ Переделал. Чет не вкуриваю, где задается параметр "IP компа, в котором нужно перечислить работающие интерфейсы и найти маски"? |
Сообщ.
#11
,
|
|
|
Это для локального компьютера.
Мне надо для локального компьютера. Я делаю работу с двумя интернет подключениями на одном компьютере, поэтому надо сравнивать ipv4 адреса и маски. |
Сообщ.
#12
,
|
|
|
Цитата Kozlov_Sergey @ Сейчас стоит задача определить маску по ipv4 и каким-то ещё параметрам в общем случае (не для текущего компьютера). Цитата Kozlov_Sergey @ Мне надо для локального компьютера. |
Сообщ.
#13
,
|
|
|
ОМГ
Добавлено Я правильно понял, что вся задача ТС сводится к применению маски к 2 адресам и их последующему сравнению? |
Сообщ.
#14
,
|
|
|
Написал, отладил, проверил - работает для 2 интернетов на 1 компьютере.
Перенаправление портов одновременно на 2 модемах через upnp работает. Приходилось работать через диагностические MessageBox и копировать exe файл через TeamViewer на компьютер с 2 сетями. Так долго делал, потому что для второго интернет соединения не работало, потому что в одном месте надо было проверять на символ '\n', а во втором +1 поставить где надо. Это было трудно понять по диагностическим сообщениям. А мощности Wi-Fi TP-Link не хватало до компьютера с Visual Studio 2012. Теперь программа ожидает проверки на 2 модемах с публичными динамическими адресами, а не как у провайдеров с собственной подсетью. В программе осталась куча диагностических сообщений, которые ещё рано убирать. Работает для модемов TP-Link какой-то Wi-Fi и ZyXEL Keenetic Dsl. Теперь ждём замены кривого Bilion (с которым даже Windows не работает) и TP-Link какой-то Wi-Fi на TP-Link Wi-Fi Dsl. Разбираться с Bilion не стал. На ноутбуке не установлена Visual Studio 2012. |
Сообщ.
#15
,
|
|
|
Вот функции:
#include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> #include <stdio.h> #include <string> #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "ws2_32.lib") #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) /* Note: could also use malloc() and free() */ bool get_ipv4_and_mask(std::string &result) { int i; /* Variables used by GetIpAddrTable */ PMIB_IPADDRTABLE pIPAddrTable; DWORD dwSize = 0; DWORD dwRetVal = 0; IN_ADDR IPAddr; /* Variables used to return error message */ LPVOID lpMsgBuf; // Before calling AddIPAddress we use GetIpAddrTable to get // an adapter to which we can add the IP. pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE)); if (pIPAddrTable) { // 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); } if (pIPAddrTable == NULL) { // printf("Memory allocation failed for GetIpAddrTable\n"); return false; } } // Make a second call to GetIpAddrTable to get the // actual data we want if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) != NO_ERROR ) { // printf("GetIpAddrTable failed with error %d\n", dwRetVal); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL)) { // printf("\tError: %s", lpMsgBuf); LocalFree(lpMsgBuf); } return false; } //printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { //printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; //printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); result += inet_ntoa(IPAddr); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; //printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); result += std::string("/"); result += inet_ntoa(IPAddr); result += std::string("\n"); //IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; /*/ printf("\tBroadCast[%d]: \t%s (%ld%)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); printf("\tType and State[%d]:", i); if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY) printf("\tPrimary IP Address"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC) printf("\tDynamic IP Address"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED) printf("\tAddress is on disconnected interface"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED) printf("\tAddress is being deleted"); if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT) printf("\tTransient address"); printf("\n"); /*/ } if (pIPAddrTable) { FREE(pIPAddrTable); pIPAddrTable = NULL; } return true; } bool are_ipv4_from_one_subnet(std::string parameter_local_computer_1_ipv4,std::string parameter_computer_2_ipv4) { std::string local_result; if(get_ipv4_and_mask(local_result)) { std::string::size_type pos_1 = local_result.find(parameter_local_computer_1_ipv4); if(pos_1!=std::string::npos) { ::MessageBoxA(NULL,parameter_local_computer_1_ipv4.c_str(),"Found ipv4",0); std::string::size_type pos_2 = local_result.find("/",pos_1); if(pos_2!=std::string::npos) { ::MessageBoxA(NULL,parameter_local_computer_1_ipv4.c_str(),"Found /",0); std::string parameter_computer_1_ipv4_mask; for(std::string::size_type mask_counter=pos_2+1;mask_counter<local_result.length();mask_counter++) { char local_char = local_result.at(mask_counter); if(local_char!='\n') { parameter_computer_1_ipv4_mask += local_char; } else { break; } } ::MessageBoxA(NULL,CStringA(parameter_local_computer_1_ipv4.c_str()) + CStringA("/") + CStringA(parameter_computer_1_ipv4_mask.c_str()),parameter_computer_2_ipv4.c_str(),MB_ICONINFORMATION); if( (convert_ipv4_to_dword(parameter_local_computer_1_ipv4)&convert_ipv4_to_dword(parameter_computer_1_ipv4_mask)) == (convert_ipv4_to_dword(parameter_computer_2_ipv4)&convert_ipv4_to_dword(parameter_computer_1_ipv4_mask)) ) { return true; } } } } return false; } DWORD convert_ipv4_to_dword(std::string parameter_ipv4) { BYTE b1 = 0; BYTE b2 = 0; BYTE b3 = 0; BYTE b4 = 0; std::string bs1; std::string bs2; std::string bs3; std::string bs4; std::string::size_type counter=0; for(;counter<parameter_ipv4.length();counter++) { char local_char = parameter_ipv4.at(counter); if(local_char!='.') { bs1 += local_char; } else { break; } } for(counter++;counter<parameter_ipv4.length();counter++) { char local_char = parameter_ipv4.at(counter); if(local_char!='.') { bs2 += local_char; } else { break; } } for(counter++;counter<parameter_ipv4.length();counter++) { char local_char = parameter_ipv4.at(counter); if(local_char!='.') { bs3 += local_char; } else { break; } } for(counter++;counter<parameter_ipv4.length();counter++) { char local_char = parameter_ipv4.at(counter); if(local_char!='.') { bs4 += local_char; } else { break; } } b1 = atoi(bs1.c_str()); b2 = atoi(bs2.c_str()); b3 = atoi(bs3.c_str()); b4 = atoi(bs4.c_str()); return (DWORD(b1)<<24)|(DWORD(b2)<<16)|(DWORD(b3)<<8)|(DWORD(b4)); } Пример использования: if(network::ip_4::are_ipv4_from_one_subnet(std::string(local_current_address),std::string(info.ip))) { ::MessageBox(0,CString(local_current_address) + CString(L"\n") + CString(info.ip.c_str()),CString(L"are_ipv4_from_one_subnet == true"),MB_ICONINFORMATION); UPNPNATHTTPClient soap( info.ip, info.port ); UPNPNATHTTPClient::SoapResult soap_res; soap_res = soap.AddPortMapping( std::string("stl_network_ip_4_ppp_6_udp_engine"), std::string(local_current_address.GetBuffer()), local_parameter_port_number_local, local_parameter_port_number_local, std::string("UDP"), info.ip, info.control_url, info.service_type ); if( UPNPNATHTTPClient::SoapSucceeded == soap_res ) { local_main_dialog->redirected_port_number = local_parameter_port_number_local; CString local_message("portmapping succeeded."); CString local_error_message; local_error_message.Format(L"%s\nlocal_current_address == %s\nlocal_parameter_port_number_local == %d",local_message,CString(local_current_address).GetBuffer(),local_parameter_port_number_local); ::MessageBox(0,local_error_message,CString(L"Information"),MB_ICONINFORMATION); local_wan_ppp_AddPortMapping_udp_failed = false; } else if(local_main_dialog->redirected_port_number==0) { CString local_error_message; CString local_message("local_wan_ppp_AddPortMapping_udp_failed = true;"); local_error_message.Format(L"%s\nlocal_current_address == %s\nlocal_parameter_port_number_local == %d",local_message,CString(local_current_address).GetBuffer(),local_parameter_port_number_local); ::MessageBox(0,local_error_message,CString(L"Information"),MB_ICONINFORMATION); local_wan_ppp_AddPortMapping_udp_failed = true; } else { CString local_error_message; CString local_message("local_wan_ppp_AddPortMapping_udp_failed = true;\nlocal_main_dialog->redirected_port_number!=0"); local_error_message.Format(L"%s\nlocal_current_address == %s\nlocal_parameter_port_number_local == %d",local_message,CString(local_current_address).GetBuffer(),local_parameter_port_number_local); ::MessageBox(0,local_error_message,CString(L"Information"),MB_ICONINFORMATION); } } |