局域网广播收发

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <assert.h>

using namespace std;

#define BROADCAST_PORT 8186
#define MAX_IPC_NUM 100
#define MAX_TIMEOUT 1

#define M_DBG(fmt, ...) \
do\
{\
    printf("%s:%d: "fmt"\n", __FILE__, __LINE__, ##__VA_ARGS__);\
}while(0)

#define M_RETURN(exr, ret, fmt, ...) \
do\
{\
    if (!(exr))\
    {\
        M_DBG(fmt, ##__VA_ARGS__);\
        return ret;\
    }\
}while(0)

#define M_PRINTF(exr, fmt, ...) \
do\
{\
    if (!(exr))\
    {\
        M_DBG(fmt, ##__VA_ARGS__);\
    }\
}while(0)

#define _ArraySize(a) (sizeof(a)/sizeof(a[0]))

typedef struct
{
    bool valid;
    char szWorkNic[24];
    char szId[24];
    char szServer[24];
    char szMAC[24];
    char szIp[24];
    char szGateway[24];
    char szMask[24];
    char szDns0[24]; 
    char szDns1[24];
    char szSession[24];
}IPC_INFO_S;

typedef struct
{
    int recv_port;
    IPC_INFO_S astIpcInfo[MAX_IPC_NUM];
}RUNNING_PARAMS_S;


static bool _ShowIpcInfo(RUNNING_PARAMS_S* _pstRunParams)
{
    int i = 0;
    printf("| %-8s | %-17s | %-16s | %-16s | %-20s | %-5s |\n", 
                    "IPC-ID", "IPC-MAC", "IPC-IP", "IPC-GATEWAY", "IPC-SERVER", "NIC");
    for (i = 0; i < _ArraySize(_pstRunParams->astIpcInfo); i++)
    {
        if (!_pstRunParams->astIpcInfo[i].valid)
        {
            continue;
        }
        IPC_INFO_S* pstTmp = &_pstRunParams->astIpcInfo[i];
        printf("| %-8s | %-17s | %-16s | %-16s | %-20s | %-5s |\n", pstTmp->szId, pstTmp->szMAC, pstTmp->szIp, 
                pstTmp->szGateway,pstTmp->szServer, pstTmp->szWorkNic);
    }
    printf("\n\n\n\n\n\n");
    return true;
}

static bool _ShowIpcInfo1(RUNNING_PARAMS_S* _pstRunParams)
{
    int i = 0;
    printf("| %-8s | %-17s | %-16s | %-16s | %-16s | %-16s | %-16s | %-20s | %-5s |\n", 
                    "IPC-ID", "IPC-MAC", "IPC-IP", "IPC-GATEWAY", "IPC-MASK","IPC-DNS0","IPC-DNS1","IPC-SERVER", "NIC");
    for (i = 0; i < _ArraySize(_pstRunParams->astIpcInfo); i++)
    {
        if (!_pstRunParams->astIpcInfo[i].valid)
        {
            continue;
        }
        IPC_INFO_S* pstTmp = &_pstRunParams->astIpcInfo[i];
        printf("| %-8s | %-17s | %-16s | %-16s | %-16s | %-16s | %-16s | %-20s | %-5s |\n", pstTmp->szId, pstTmp->szMAC, pstTmp->szIp, 
                pstTmp->szGateway, pstTmp->szMask,pstTmp->szDns0,pstTmp->szDns1,pstTmp->szServer, pstTmp->szWorkNic);
    }
    printf("\n\n\n\n\n\n");
    return true;
}
static bool _FindStr(char* _szInput, const char* _szKey)
{
    bool bRet = false;
    char* szValue = NULL;

    szValue = strstr(_szInput, _szKey);
    if(szValue != NULL)
    {
        bRet = true;
    }
    return bRet;
}

static int _SetupBroadCastSock(int _port)
{
    M_RETURN(_port > 0 && _port < 65536, false, "invalid port[%d]", _port);
    
    // 绑定地址
    struct sockaddr_in addrto;
    bzero(&addrto, sizeof(struct sockaddr_in));
    addrto.sin_family = AF_INET;
    addrto.sin_addr.s_addr = htonl(INADDR_ANY);
    addrto.sin_port = htons(_port);

    int sock = -1;
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
    {   
        M_DBG("socket error, %s", strerror(errno));
        close(sock);
        return -1;
    } 

    const int opt = 1;
    //设置该套接字为广播类型,
    int nb = 0;
    nb = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
    if(nb == -1)
    {
        M_DBG("setsockopt broadcast error, %s", strerror(errno));
        close(sock);
        return -1;
    }
    
    struct timeval timeout = {MAX_TIMEOUT, 0};
    nb = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(struct timeval));
    if(nb == -1)
    {
        M_DBG("setsockopt timeout error, %s", strerror(errno));
        close(sock);
        return -1;
    }

    if(bind(sock,(struct sockaddr *)&(addrto), sizeof(struct sockaddr_in)) == -1) 
    {   
        M_DBG("setsockopt error, %s", strerror(errno));
        close(sock);
        return -1;
    }
    return sock;
}

static bool _RecvDataOverBroadCast(int _sock, char* _szTmp, int _len)
{
    M_RETURN(_sock > 0, false, "invalid sock[%d]", _sock);
    
    memset(_szTmp, 0, _len);
    
    //int ret = recvfrom(sock, _szTmp, _len, 0, (struct sockaddr*)&from,(socklen_t*)&len);
    int ret = recvfrom(_sock, _szTmp, _len, 0, NULL, NULL);
    if(ret<=0)
    {
        if (errno == EAGAIN || errno == EINTR)
        {
            M_DBG("setsockopt time out, %s", strerror(errno));
            //close(_sock);
            return false;
        }
        else
        {
            M_DBG("setsockopt error, %s", strerror(errno));
            //close(_sock);
            return false;
        }
    }
    else
    {		
        M_DBG("recv ok[%d bytes]:\n%s", ret, _szTmp);	
    }
    //close(_sock);
    
    return true;
}

static bool _SendDataOverBroadCast(const char* _szTmp, int _len, int _port)
{
    int sock = -1;
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
    {   
        M_DBG("socket error, %s", strerror(errno));
        close(sock);
        return false;
    }

    const int opt = 1;
    //设置该套接字为广播类型,
    int nb = 0;
    nb = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
    if(nb == -1)
    {
        M_DBG("setsockopt error, %s", strerror(errno));
        close(sock);
        return false;
    }

    struct timeval timeout = {MAX_TIMEOUT, 0};
    nb = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(struct timeval));
    if(nb == -1)
    {
        M_DBG("setsockopt timeout error, %s", strerror(errno));
        close(sock);
        return false;
    }
    
    struct sockaddr_in addrto;
    bzero(&addrto, sizeof(struct sockaddr_in));
    addrto.sin_family = AF_INET;
    addrto.sin_addr.s_addr = htonl(INADDR_BROADCAST);
    addrto.sin_port = htons(_port);
    int nlen = sizeof(addrto);

    int ret = sendto(sock, _szTmp, _len, 0, (struct sockaddr*)&addrto, nlen);
    if(ret <= 0)
    {
        M_DBG("send error, %s", strerror(errno));
        close(sock);
        return false;
    }
    else
    {		
        M_DBG("send ok[%d bytes] over broadcast port %d", ret, _port);	
    }
    close(sock);
    return true;
}

static bool _GetKeyValue(char* _szTmp, const char* _szKey, char* _szValue, int _Len)
{
    bool bRet = false;
    char* szValue = NULL;
    char* szReturn = NULL;

    memset(_szValue, 0, _Len);
    szValue = strstr(_szTmp, _szKey);
    if(szValue != NULL)
    {
        szValue += strlen(_szKey);
        szReturn = strstr(szValue, "\r\n");
        if(szReturn != NULL)
        {
            assert(szReturn - szValue <= _Len);
            memcpy(_szValue, szValue, szReturn - szValue);
            _szValue[szReturn - szValue] = 0;
            bRet = true;
        }
    }
    return bRet;
}

static int _GetErrCode(char* _szTmp)
{
    char szStatusCode[24];
    memset(szStatusCode, 0, sizeof(szStatusCode));
    
    bool ret = _GetKeyValue(_szTmp, "AJB-IPC/1.0 ", szStatusCode, sizeof(szStatusCode));
    M_RETURN(ret, -1, "get error code failed. %s", _szTmp);
    
    return atoi(szStatusCode);
}

// FilterRepeat and find a valid node
static int _FindAvailable(const char* szMAC, IPC_INFO_S* _pstIpcInfo, int _num)
{
    assert(_num <= MAX_IPC_NUM);
    int i = 0;
    for (i = 0; i < _num; i++)
    {
        if (_pstIpcInfo[i].valid)
        {
            if (!strcmp(_pstIpcInfo[i].szMAC, szMAC))
            {
                return i;
            }
        }
        else
        {
            return i;
        }
    }
    M_DBG("IpcInfo list is full[%d]", i);
    
    return -1;
}

static bool _ParseData(char* _szTmp, int _szlen, IPC_INFO_S* _pstIpcInfo, int _num)
{
    char szMAC[24];
    memset(szMAC, 0, sizeof(szMAC));
    char szDns[48];
    memset(szDns, 0, sizeof(szDns));

    bool ret = _GetKeyValue(_szTmp, "MAC: ", szMAC, sizeof(szMAC));
    M_RETURN(ret, ret, "not found MAC\n%s", _szTmp);
    
    int index = _FindAvailable(szMAC, _pstIpcInfo, _num);
    M_RETURN(index != -1, false, "find available node failed");
    M_DBG("index: %d", index);
    
    memset(&_pstIpcInfo[index], 0, sizeof(IPC_INFO_S));
    ret = _GetKeyValue(_szTmp, "Session: ", _pstIpcInfo[index].szSession, sizeof(_pstIpcInfo[index].szSession));
    M_PRINTF(ret, "not found session, %s", _szTmp); 
    ret = _GetKeyValue(_szTmp, "ID: ", _pstIpcInfo[index].szId, sizeof(_pstIpcInfo[index].szId));
    M_PRINTF(ret, "not found ID, %s", _szTmp);
    ret = _GetKeyValue(_szTmp, "Server: ", _pstIpcInfo[index].szServer, sizeof(_pstIpcInfo[index].szServer));
    M_PRINTF(ret, "not found Server, %s", _szTmp);
    ret = _GetKeyValue(_szTmp, "MAC: ", _pstIpcInfo[index].szMAC, sizeof(_pstIpcInfo[index].szMAC));
    M_PRINTF(ret, "not found MAC, %s", _szTmp);
    ret = _GetKeyValue(_szTmp, "Ip: ", _pstIpcInfo[index].szIp, sizeof(_pstIpcInfo[index].szIp));
    M_PRINTF(ret, "not found Ip, %s", _szTmp);
    ret = _GetKeyValue(_szTmp, "Gateway: ", _pstIpcInfo[index].szGateway, sizeof(_pstIpcInfo[index].szGateway));
    M_PRINTF(ret, "not found Gateway, %s", _szTmp);
    ret = _GetKeyValue(_szTmp, "Mask: ", _pstIpcInfo[index].szMask, sizeof(_pstIpcInfo[index].szMask));
    M_PRINTF(ret, "not found Mask, %s", _szTmp);
    ret = _GetKeyValue(_szTmp, "WorkNic: ", _pstIpcInfo[index].szWorkNic, sizeof(_pstIpcInfo[index].szWorkNic));
    M_PRINTF(ret, "not found WorkNic, %s", _szTmp);
    
    ret = _GetKeyValue(_szTmp, "Dns: ", szDns, sizeof(szDns));
    M_PRINTF(ret, "not found Dns, %s", _szTmp);
    if (ret)
    {
        ret = _FindStr(szDns, ";");
        if (ret)
        {
            char* Begin = szDns;
            char* Found = strstr(Begin, ";");
            M_RETURN(Found, false, "found ';' error, %s", Begin);
            strncpy(_pstIpcInfo[index].szDns0, Begin, Found - Begin);
            Found += strlen(";");
            strcpy(_pstIpcInfo[index].szDns1, Found);
        }
        else
        {
            strcpy(_pstIpcInfo[index].szDns0, szDns);
        }
    }

    _pstIpcInfo[index].valid = true;
    return true;
}

static bool _SendGetRequest(RUNNING_PARAMS_S* _pstRunParams)
{
    char szTmp[1024];
    memset(szTmp, 0, sizeof(szTmp));

    _pstRunParams->recv_port++;
    const char* szTemplate = 
            "GET AJB-IPC/1.0\r\n"
            "ClientPort: %d\r\n"
            "\r\n"
            ;
    snprintf(szTmp, sizeof(szTmp), szTemplate, _pstRunParams->recv_port);
    M_DBG("ready to send[%d bytes]:\n%s", strlen(szTmp), szTmp);
    bool ret = _SendDataOverBroadCast(szTmp, strlen(szTmp), BROADCAST_PORT);
    
    return ret; 
}

static bool _RecvResp(RUNNING_PARAMS_S* _pstRunParams, char* _szTmp, int _len)
{
    bool ret = false;

    int sock = _SetupBroadCastSock(_pstRunParams->recv_port);
    M_RETURN(sock != -1, false, "invalid sock[%d]", sock);
    
    while(1)
    {
        ret = _RecvDataOverBroadCast(sock, _szTmp, _len);
        //M_RETURN(ret, ret, "recv all complete.");
        if (!ret)
        {
            close(sock);
            break;
        }
        if (200 != _GetErrCode(_szTmp))
        {
            M_DBG("status code is not 200, continue recv:\n%s", _szTmp);
            continue;
        }
        if (!_FindStr(_szTmp, "\r\n\r\n"))
        {
            M_DBG("not found end sign, continue recv:\n%s", _szTmp);
            continue;
        }
        ret = _ParseData(_szTmp, strlen(_szTmp), _pstRunParams->astIpcInfo, _ArraySize(_pstRunParams->astIpcInfo));
    }
    
    return ret;
}

static bool _SendPostRequest(RUNNING_PARAMS_S* _pstRunParams)
{
    char szTmp[1024];
    memset(szTmp, 0, sizeof(szTmp));

    _pstRunParams->recv_port++;
    const char* szTemplate = 
                                "POST AJB-IPC/1.0\r\n"
                                "ClientPort: %d\r\n"
                                "Session: %s\r\n"
                                "ID: %x\r\n"
                                "Server: %s\r\n"
                                "MAC: %s\r\n"
                                "Ip: %s\r\n"
                                "Gateway: %s\r\n"
                                "Mask: %s\r\n"
                                "Dns: %s\r\n"
                                "\r\n"
                                ;
    char* szSession = NULL;
    int i = 0;
    for (i = 0; i < _ArraySize(_pstRunParams->astIpcInfo); i++)
    {
        if (!_pstRunParams->astIpcInfo[i].valid)
        {
            continue;
        }
        
        snprintf(szTmp, sizeof(szTmp), szTemplate, _pstRunParams->recv_port, _pstRunParams->astIpcInfo[i].szSession, 0x54325432, 
                "192.168.34.203", "00:00:22:26:f4:de", "192.168.34.211", 
                "192.168.34.254", "255.255.255.0", "5.5.5.5");
        M_DBG("ready to send[%d bytes]:\n%s", strlen(szTmp), szTmp);
        bool ret = _SendDataOverBroadCast(szTmp, strlen(szTmp), BROADCAST_PORT);
        M_RETURN(ret, ret, "send error.");
    }
    

    return true; 
}

int main()
{
    char szTmp[1024];
    memset(szTmp, 0, sizeof(szTmp));

    RUNNING_PARAMS_S stRunParams;
    memset(&stRunParams, 0, sizeof(RUNNING_PARAMS_S));

    stRunParams.recv_port = 8056;// init port
    while(1)
    {
        M_DBG("Please press ENTER to seach IPC ...");
        getchar();
        
        bool ret = _SendGetRequest(&stRunParams);
        M_RETURN(ret, ret, "send error.");
        ret = _RecvResp(&stRunParams, szTmp, sizeof(szTmp));
        M_PRINTF(ret, "recv all complete.");
        
    /*
        ret = _SendPostRequest(&stRunParams);
        M_RETURN(ret, ret, "send error.");
        ret = _RecvResp(&stRunParams, szTmp, sizeof(szTmp));
        M_PRINTF(ret, "recv all complete.");
    */

        ret = _ShowIpcInfo(&stRunParams);
        M_PRINTF(ret, "show failed.");
    }
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值