找到你要的答案

Q:Multiple Broadcast Reception on Same port but different interfaces

Q:同一端口但不同接口的多广播接收

I'm trying to build a little personal DHCP server to serve a specific scope if the broadcast is received on eth0 and another if received on wlan0 but I can't bind more than a single interface on the same address:port combination (255.255.255.255:67) I heard about SO_REUSABLE but I have no idea about how to implement it and if of course it's the good way to do it

Actually this is my code :

#include <stdio.h>   
#include <string.h> 
#include <stdlib.h> 
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <vector>

#define BUFLEN 1024
#define PORT 67
using namespace std;

char *ipAddrFromInterface(char *apInterfaceName) //this function is not from me
{
    return "255.255.255.255";

    /*char *if_name = (char *) apInterfaceName;
    struct ifreq ifr;
    size_t if_name_len = strlen(if_name);

    if(if_name_len < sizeof(ifr.ifr_name))
    {
        memcpy(ifr.ifr_name, if_name, if_name_len);
        ifr.ifr_name[if_name_len] = 0;
    }
    else
        printf("interface name is too long\n");

    int fd = socket(AF_INET, SOCK_DGRAM, 0);

    if(fd == -1)
        printf("A => %s\n", strerror(errno));

    if(ioctl(fd, SIOCGIFADDR, &ifr) == -1)
    {
        int temp_errno = errno;
        close(fd);
        printf("B => %s\n", strerror(temp_errno));
    }

    if(ioctl(fd, SIOCGIFADDR, &ifr) == -1)
    {
        int temp_errno = errno;
        close(fd);
        printf("C => %s\n", strerror(temp_errno));
    }

    close(fd);

    struct sockaddr_in* ipaddr = (struct sockaddr_in*) &ifr.ifr_addr;
    return inet_ntoa(ipaddr->sin_addr);*/
}

struct socketData
{
    int sock;
    sockaddr_in  socket;
    char *interfaceName;
};

void print(int i)
{
    printf("%d\n", i);
    fflush(stdout);
}

void server_receive_thread(vector<char*> aInterfaceList)
{
    int socketIndex = 0;
    struct sockaddr_in  localSock;
    int socketDescriptor; int socketLength;
    vector<socketData> aSockets;

    for( ; socketIndex < aInterfaceList.size(); socketIndex++)
    {
        socketData socketD;
        char *apInterfaceName = aInterfaceList.at(socketIndex);

        if((socketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
        {
            printf("can't listen on interface %s... sleeping\n", apInterfaceName);
        }
        else
        {
            memset(&localSock, 0, sizeof(localSock));
            localSock.sin_family = AF_INET;
            localSock.sin_port = htons(PORT);

            inet_aton(ipAddrFromInterface(apInterfaceName), &localSock.sin_addr);
            setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE, apInterfaceName, sizeof(apInterfaceName));

            if(bind(socketDescriptor, (struct sockaddr *) &localSock, sizeof(localSock)) == -1)
            {
                printf("can't bind interface %s to listen on port %d... sleeping\n", apInterfaceName, PORT);
            }
            else
            {
                printf("bound to interface %s on port %d\n", apInterfaceName, PORT);
                socketD.sock = socketDescriptor;
                socketD.socket = localSock;
                socketD.interfaceName = apInterfaceName;
                aSockets.push_back(socketD);
            }
        }
    }

    fd_set master;
    int fdMax = -1;
    while(1)
    {
        FD_ZERO(&master);

        for(int iSock = 0; iSock < aSockets.size(); iSock++)
        {
            socketData d = aSockets.at(iSock);
            FD_SET(d.sock, &master);

            if(d.sock > fdMax)
                fdMax = d.sock;
        }

        printf("fdmax is : ");
        print(fdMax);

        if(select(fdMax + 1, &master, NULL, NULL, NULL) == -1)
            print(2);

        print(200);

        for(int iSock = 0; iSock < aSockets.size(); iSock++)
        {
            socketData d = aSockets.at(iSock);

            if(FD_ISSET(d.sock, &master))
                print(3);
        }
        print(1);
    }
}

int main()
{
    std::vector<char*>  interfaceList;
    interfaceList.push_back("wlan0");
    interfaceList.push_back("eth0");
    server_receive_thread(interfaceList);
    return 0;
}

I'm trying to build a little personal DHCP server to serve a specific scope if the broadcast is received on eth0 and another if received on wlan0 but I can't bind more than a single interface on the same address:port combination (255.255.255.255:67) I heard about SO_REUSABLE but I have no idea about how to implement it and if of course it's the good way to do it

其实这是我的代码:

#include <stdio.h>   
#include <string.h> 
#include <stdlib.h> 
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <vector>

#define BUFLEN 1024
#define PORT 67
using namespace std;

char *ipAddrFromInterface(char *apInterfaceName) //this function is not from me
{
    return "255.255.255.255";

    /*char *if_name = (char *) apInterfaceName;
    struct ifreq ifr;
    size_t if_name_len = strlen(if_name);

    if(if_name_len < sizeof(ifr.ifr_name))
    {
        memcpy(ifr.ifr_name, if_name, if_name_len);
        ifr.ifr_name[if_name_len] = 0;
    }
    else
        printf("interface name is too long\n");

    int fd = socket(AF_INET, SOCK_DGRAM, 0);

    if(fd == -1)
        printf("A => %s\n", strerror(errno));

    if(ioctl(fd, SIOCGIFADDR, &ifr) == -1)
    {
        int temp_errno = errno;
        close(fd);
        printf("B => %s\n", strerror(temp_errno));
    }

    if(ioctl(fd, SIOCGIFADDR, &ifr) == -1)
    {
        int temp_errno = errno;
        close(fd);
        printf("C => %s\n", strerror(temp_errno));
    }

    close(fd);

    struct sockaddr_in* ipaddr = (struct sockaddr_in*) &ifr.ifr_addr;
    return inet_ntoa(ipaddr->sin_addr);*/
}

struct socketData
{
    int sock;
    sockaddr_in  socket;
    char *interfaceName;
};

void print(int i)
{
    printf("%d\n", i);
    fflush(stdout);
}

void server_receive_thread(vector<char*> aInterfaceList)
{
    int socketIndex = 0;
    struct sockaddr_in  localSock;
    int socketDescriptor; int socketLength;
    vector<socketData> aSockets;

    for( ; socketIndex < aInterfaceList.size(); socketIndex++)
    {
        socketData socketD;
        char *apInterfaceName = aInterfaceList.at(socketIndex);

        if((socketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
        {
            printf("can't listen on interface %s... sleeping\n", apInterfaceName);
        }
        else
        {
            memset(&localSock, 0, sizeof(localSock));
            localSock.sin_family = AF_INET;
            localSock.sin_port = htons(PORT);

            inet_aton(ipAddrFromInterface(apInterfaceName), &localSock.sin_addr);
            setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE, apInterfaceName, sizeof(apInterfaceName));

            if(bind(socketDescriptor, (struct sockaddr *) &localSock, sizeof(localSock)) == -1)
            {
                printf("can't bind interface %s to listen on port %d... sleeping\n", apInterfaceName, PORT);
            }
            else
            {
                printf("bound to interface %s on port %d\n", apInterfaceName, PORT);
                socketD.sock = socketDescriptor;
                socketD.socket = localSock;
                socketD.interfaceName = apInterfaceName;
                aSockets.push_back(socketD);
            }
        }
    }

    fd_set master;
    int fdMax = -1;
    while(1)
    {
        FD_ZERO(&master);

        for(int iSock = 0; iSock < aSockets.size(); iSock++)
        {
            socketData d = aSockets.at(iSock);
            FD_SET(d.sock, &master);

            if(d.sock > fdMax)
                fdMax = d.sock;
        }

        printf("fdmax is : ");
        print(fdMax);

        if(select(fdMax + 1, &master, NULL, NULL, NULL) == -1)
            print(2);

        print(200);

        for(int iSock = 0; iSock < aSockets.size(); iSock++)
        {
            socketData d = aSockets.at(iSock);

            if(FD_ISSET(d.sock, &master))
                print(3);
        }
        print(1);
    }
}

int main()
{
    std::vector<char*>  interfaceList;
    interfaceList.push_back("wlan0");
    interfaceList.push_back("eth0");
    server_receive_thread(interfaceList);
    return 0;
}
answer1: 回答1:

You don't need a socket per interface. Just bind a single socket to 0.0.0.0 and the desired port. Then it will receive via all interfaces. You certainly can't, and don't need to, bind to 255.255.255.255.

Or, bind it to the single IP address that is connected to the scope you want to serve.

每个接口不需要套接字。只绑定一个单一的插座为0.0.0.0和所需的端口。然后它将通过所有接口接收。你当然不会,也不需要绑定到255.255.255.255。

或者,将其绑定到连接到要服务的作用域的单个IP地址。

c++  linux  udp  broadcast  dhcp