我是靠谱客的博主 内向舞蹈,最近开发中收集的这篇文章主要介绍windows C++ 通过UDP广播获取网络中所有设备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: %sn", pIPAddr);
                printf("receive command: %sn", 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 %dn", 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 %dn", 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 %dn", 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:%sn", 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 %dn", err);   
            return -1;   
        }   
        buff[nSendSize] = '';   
        printf("received ip: %sn", buff);   
    }   

    return 0;   
}  

运行结果

  • 1.Server端
    这里写图片描述
  • 2.Client端
    这里写图片描述
    运行结果说明:两个ip地址一样,是因为client和server我都运行在同一台机器上,如果有多台server,则client可以搜素到多个ip,受到条件限制,这里只有一个。

最后

以上就是内向舞蹈为你收集整理的windows C++ 通过UDP广播获取网络中所有设备ip地址的全部内容,希望文章能够帮你解决windows C++ 通过UDP广播获取网络中所有设备ip地址所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部