windows C++ 通过UDP广播获取网络中所有设备ip地址
2017-02-17 11:47
891 查看
说明:
源码下载地址:http://download.csdn.net/detail/dxzysk/9756896
源码使用说明,先在需要获取IP地址的主机上运行server端程序,然后在需要搜索主机的Pc上运行client端程序
本文是windows版,VC++,在VS2010环境下调试成功。有时候需要搜索网络中的设备,机器,服务器等,这就要要用到UDP广播的方式,发送广播命令,广播给网络中的每一个主机,该主机或设备接收到广播命令后,立刻发送给请求端自己的设备信息,这里以IP信息为例子。
思路
在每一个设备中部署sever端程序进行监控,client端发送广播命令,每一个server收到命令后,返回给client自己的ip地址信息,给出代码如下,其中,有部分,比如获取ip地址参考来自网络,尊重原创,乐于分享。
注意上面是只有一个Ip地址的情况,有的机器可能会有多个IP地址,不同的网络,有线网,无线wifi等,需要获取多个ip地址的方法:
2.Client端
运行结果说明:两个ip地址一样,是因为client和server我都运行在同一台机器上,如果有多台server,则client可以搜素到多个ip,受到条件限制,这里只有一个。
源码下载地址:http://download.csdn.net/detail/dxzysk/9756896
源码使用说明,先在需要获取IP地址的主机上运行server端程序,然后在需要搜索主机的Pc上运行client端程序
本文是windows版,VC++,在VS2010环境下调试成功。有时候需要搜索网络中的设备,机器,服务器等,这就要要用到UDP广播的方式,发送广播命令,广播给网络中的每一个主机,该主机或设备接收到广播命令后,立刻发送给请求端自己的设备信息,这里以IP信息为例子。
思路
在每一个设备中部署sever端程序进行监控,client端发送广播命令,每一个server收到命令后,返回给client自己的ip地址信息,给出代码如下,其中,有部分,比如获取ip地址参考来自网络,尊重原创,乐于分享。
server端(windows控制台程序)
server端监听广播命令”GetIPAddr”,收到命令后就相应#include <WinSock2.h> #include <stdio.h> #include <iostream> using namespace std; #pragma comment(lib, "ws2_32.lib") #define GET_HOST_COMMAND "GetIPAddr" const int MAX_BUF_LEN = 255; #define SERVER_PORT 12811 //只返回一个ip地址 bool GetLocalIP(char* ip) { //1.初始化wsa WSADATA wsaData; int ret=WSAStartup(MAKEWORD(2,2),&wsaData); if (ret!=0) { return false; } //2.获取主机名 char hostname[256]; ret=gethostname(hostname,sizeof(hostname)); if (ret==SOCKET_ERROR) { return false; } //3.获取主机ip HOSTENT* host=gethostbyname(hostname); if (host==NULL) { return false; } //4.转化为char*并拷贝返回 strcpy(ip,inet_ntoa(*(in_addr*)*host->h_addr_list)); return true; } bool doServer(){ int m_nPort = SERVER_PORT; SOCKET sClient; sockaddr_in clientAddr,bindAddr; WSADATA wsdata; //启动SOCKET库,版本为2.0 WORD wVer=MAKEWORD(2,0); if( 0 != WSAStartup(wVer,&wsdata) ) { //AfxMessageBox(L"Not Support Socket2.0"); return false; } //用UDP初始化套接字 sClient=socket(AF_INET,SOCK_DGRAM,0); //设置该套接字为广播类型, BOOL optval=TRUE; bindAddr.sin_family=AF_INET; bindAddr.sin_addr.s_addr=htonl(INADDR_ANY); bindAddr.sin_port=htons(m_nPort); setsockopt(sClient,SOL_SOCKET,SO_BROADCAST,(char FAR *)&optval,sizeof(optval)); bind(sClient,(sockaddr *)&bindAddr,sizeof(sockaddr_in)); int nAddrLen = sizeof(SOCKADDR); char buf[256] = {0}; int fromlength=sizeof(SOCKADDR); printf("the server is start.\n"); char ipaddr[30] = {0}; char buff[MAX_BUF_LEN] = ""; if (GetLocalIP(ipaddr)) { sprintf(buff, "my ip is:%s", ipaddr); } else { sprintf(buff, "%s", "my ip is:******"); } //有多个ip地址的时候,这样调用 //IPInfo ips[10]; //int len1 = 0; //GetLocalIPs(ips, 10,&len1); while(true) { int nRet = recvfrom(sClient,buf,256,0,(struct sockaddr FAR *)&clientAddr,(int FAR *)&fromlength); if( SOCKET_ERROR != nRet ) { char *pIPAddr = inet_ntoa(clientAddr.sin_addr); if( NULL != pIPAddr ) { WCHAR wzIPBuffer[32] = {0}; printf("clientAddr: %s\n", pIPAddr); printf("receive command: %s\n", buf); } if (strcmp(buf,GET_HOST_COMMAND) != 0) { printf("the command not valid and was ignored.\n", buf); continue; } // 发送数据 int nSendSize = sendto(sClient, buff, strlen(buff), 0, (SOCKADDR*)&clientAddr, nAddrLen); if(SOCKET_ERROR == nSendSize) { int err = WSAGetLastError(); printf("\"sendto\" error!, error code is %d\n", err); return false; } } else { //AfxMessageBox(L"Recv UDP Failed"); } Sleep(1000); } closesocket(sClient); return true; } int main() { if (!doServer()) { printf("sever returned an error"); return -1; } return 0; }
注意上面是只有一个Ip地址的情况,有的机器可能会有多个IP地址,不同的网络,有线网,无线wifi等,需要获取多个ip地址的方法:
//结构体记录ip信息 typedef struct tagIPInfo { char ip[30]; }IPInfo; //获取多个ip地址信息列表 bool GetLocalIPs(IPInfo* ips,int maxCnt,int* cnt) { //1.初始化wsa WSADATA wsaData; int ret=WSAStartup(MAKEWORD(2,2),&wsaData); if (ret!=0) { return false; } //2.获取主机名 char hostname[256]; ret=gethostname(hostname,sizeof(hostname)); if (ret==SOCKET_ERROR) { return false; } //3.获取主机ip HOSTENT* host=gethostbyname(hostname); if (host==NULL) { return false; } //4.逐个转化为char*并拷贝返回 *cnt=host->h_length<maxCnt?host->h_length:maxCnt; for (int i=0;i<*cnt;i++) { in_addr* addr=(in_addr*)*host->h_addr_list; strcpy(ips[i].ip,inet_ntoa(addr[i])); } return true; }
client端(windows控制台程序)
client端发送”GetIPAddr”命令,并及时接收client端发过来的信息//#include "stdafx.h" #include <WinSock2.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") const int MAX_BUF_LEN = 255; #define GET_HOST_COMMAND "GetIPAddr" #define CLIENT_PORT 11121 #define SERVER_PORT 12811 int main() { int nPort = SERVER_PORT; WORD wVersionRequested; WSADATA wsaData; int err; // 启动socket api wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return -1; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { WSACleanup( ); return -1; } // 创建socket SOCKET connect_socket; connect_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(INVALID_SOCKET == connect_socket) { err = WSAGetLastError(); printf("\"socket\" error! error code is %d\n", err); return -1; } // 用来绑定套接字 SOCKADDR_IN sin; sin.sin_family = AF_INET; sin.sin_port = htons(CLIENT_PORT); sin.sin_addr.s_addr = 0; // 用来从网络上的广播地址接收数据 SOCKADDR_IN sin_from; sin_from.sin_family = AF_INET; sin_from.sin_port = htons(nPort); sin_from.sin_addr.s_addr = INADDR_BROADCAST; //设置该套接字为广播类型, bool bOpt = true; setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt)); // 绑定套接字 err = bind(connect_socket, (SOCKADDR*)&sin, sizeof(SOCKADDR)); if(SOCKET_ERROR == err) { err = WSAGetLastError(); printf("\"bind\" error! error code is %d\n", err); return -1; } printf("the client is start.\n"); int nAddrLen = sizeof(SOCKADDR); char buff[MAX_BUF_LEN] = ""; int nLoop = 0; char szMsg[]=GET_HOST_COMMAND; int nLen=sizeof(sin_from); if( SOCKET_ERROR==sendto(connect_socket, szMsg, strlen(szMsg), 0, (sockaddr*)&sin_from, nLen) ) { // AfxMessageBox(L"Send UDP Failed"); return -1; } printf("send broadcast data:%s\n", GET_HOST_COMMAND); while(true) { // 接收数据 int nSendSize = recvfrom(connect_socket, buff, MAX_BUF_LEN, 0, (SOCKADDR*)&sin_from, &nAddrLen); if(SOCKET_ERROR == nSendSize) { err = WSAGetLastError(); printf("\"recvfrom\" error! error code is %d\n", err); return -1; } buff[nSendSize] = '\0'; printf("received ip: %s\n", buff); } return 0; }
运行结果
1.Server端2.Client端
运行结果说明:两个ip地址一样,是因为client和server我都运行在同一台机器上,如果有多台server,则client可以搜素到多个ip,受到条件限制,这里只有一个。
相关文章推荐
- windows C++ 通过UDP广播获取网络中所有设备ip地址
- 通过UDP广播获取网络中所有设备ip地址
- QT 通过UDP广播获取网络中所有设备ip地址
- QT 通过UDP广播获取网络中所有设备信息
- 通过Python在windows和linux中获取当前网络IP地址的一些方法
- iOS 怎样通过UDP发送广播寻找设备,拿到ip地址,然后用TCP 连接设备
- 通过UDP广播自动获取IP地址
- WINDOWS下C++通过域名获取IP地址
- 同wifi环境下android设备自动获取socket服务端的ip地址和端口号的方法-UDP广播
- 1月14日苹果在线商店促销,冲动之下购买了IMAC。以前一直在旧电脑windows下使用itunes,现在有了新的也想借此机会将旧电脑系统重装。于是我需要把现有设备中的所有资料通过itunes全部导
- 通过socket获取本机网络接口的IP地址和状态
- C++ 获取所有USB设备 列举所有USB设备 列举所有USB HUB
- C# 网络编程之通过ip地址获取地理位置(补充)
- C++ 中通过GetAdaptersInfo获取网卡配置和Ip地址信息
- 使用C++获取文件夹中所有文件名(windows环境)
- C# 网络编程之通过ip地址获取地理位置(补充)
- C/C++ windows获取本机ip地址
- C++ 中通过GetAdaptersInfo获取网卡配置和Ip地址信息
- QT5下获取本机IP地址、计算机名、网络连接名、MAC地址、子网掩码、广播地址
- C++ 网络编程之正确使用UDP广播及多播