从不同的网络接口接收UDP数据包

时间:2017-04-13 15:40:11

标签: c++ multithreading sockets networking serversocket

逗人,

如果你能引导我解决这个问题,我将不胜感激。

首先,让我介绍一下这个场景。

情景是: - 一台具有两个网络接口的设备作为发送方。 - 一个带有两个网络接口的设备作为接收器。

我们正在尝试模拟能够从移动网络(例如4G)和wifi网络接收数据包的移动设备。

必须使用UDP套接字完成通信。

发件人通过两个接口(不是并行)随机发送数据包。 接收方必须准备好接收来自每个接口的数据包

接收器和发送器都有两个UDP套接字。每个UDP套接字都分配给不同的环回接口(127.0.0.1和127.0.0.2),并具有相同的端口号(不同的IP,相同的端口号)。

sockaddr_in结构是serverAddr:

serverAddr[i].sin_family = AF_INET;
serverAddr[i].sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr[i].sin_port = htons(PORTNUM);
setsockopt(socketFileDescriptor[i], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int));

接收器在recvfrom方法中阻塞了两个线程。程序启动时,两个线程都在等待数据包。无论哪个客户端接口发送第一个数据包,从第二个数据包开始,每个新数据包似乎都被127.0.0.1接口接收。我知道INADDR_ANY允许接收发往任何接口的数据包。

我的怀疑是:为什么不再在127.0.0.2接口接收数据包了?监听来自不同网络接口的数据包的正确方法是什么?

服务器端代码:

struct info {
    int socketDescriptor;
    struct sockaddr_in addr;
    unsigned int size;
};


int udpEchoServer();
void *connection_handler(void *socketInfo);

int main(int argc, char** argv)
{

    udpEchoServer();

    puts("Press any key to continue");
    getc(stdin);

    return EXIT_SUCCESS;
}



int udpEchoServer()
{
    int socketFileDescriptor[NUM_CONNECTIONS], enable = 1, client_sock;
    struct sockaddr_in serverAddr[NUM_CONNECTIONS];
    //struct sockaddr_in clientAddr;
    info socketInfo[NUM_CONNECTIONS];
    pthread_t thread[NUM_CONNECTIONS];
    const char* interfaces[] = {"127.0.0.1", "127.0.0.2"};

    for (int i = 0; i < NUM_CONNECTIONS; i++){
        socketFileDescriptor[i] = socket(AF_INET, SOCK_DGRAM, 0);
        if(socketFileDescriptor[i] == -1) {
            perror("Error on socket creation\n");
            return EXIT_FAILURE;
        }
        if (setsockopt(socketFileDescriptor[i], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
            printf("setsockopt(SO_REUSEADDR) failed");

        bzero(&serverAddr[i], sizeof(serverAddr[i]));

        serverAddr[i].sin_family = AF_INET;
        serverAddr[i].sin_addr.s_addr = htonl(INADDR_ANY);
        serverAddr[i].sin_port = htons(PORTNUM);

        if (bind(socketFileDescriptor[i], (struct sockaddr*)& serverAddr, sizeof(serverAddr)) == -1) {
            close(socketFileDescriptor[i]);
            perror("bind failed socket\n");
            return EXIT_FAILURE;
        }


        printf("Socket #%d listening\n", socketFileDescriptor[i]);



        socketInfo[i].socketDescriptor = socketFileDescriptor[i];
        socketInfo[i].addr = serverAddr[i];
        socketInfo[i].size = sizeof(serverAddr[i]);
    }



    printf("Waiting incomming!!\n");
    int nThreads = 0;


    while (nThreads < NUM_CONNECTIONS)
    {


        printf("++++++ Creating reception thread %d\n", nThreads);
        if( pthread_create( &thread[nThreads] , NULL ,  connection_handler , (void*) &socketInfo[nThreads]) < 0)
        {
            perror("could not create thread");
            return EXIT_FAILURE;
        }
        sleep(1);
        /
        printf("nThreads = %d\n", nThreads++);
    }

    for (int i = 0; i < NUM_CONNECTIONS; i++) {
        pthread_join(thread[i], NULL);
    }



    return EXIT_SUCCESS;
}

void *connection_handler(void *socketInfo)
{
    //Get the socket descriptor
    info *newSocketInfo = (info*)socketInfo;
    int n;//, local_sock;
    char clientname[200];
    pthread_t self_id;
    self_id=pthread_self();

    while (true) {
        printf("=========> Waiting connection in thread #%u\n", self_id);
        printf("newSocketInfo->socketDescriptor = %d\n", newSocketInfo->socketDescriptor);
        printf("Adress = %s\n",inet_ntop(AF_INET,&newSocketInfo->addr.sin_addr, clientname, sizeof(clientname)));



        char client_message[2000];

        printf("Waiting packets\n");

        n = recvfrom(newSocketInfo->socketDescriptor, client_message, sizeof(client_message), 0, (struct sockaddr *)&newSocketInfo->addr, &newSocketInfo->size);

        sleep(1);
        printf("++ %d Bytes received at %d. Sending it back\n", n, newSocketInfo->socketDescriptor);
        sendto(newSocketInfo->socketDescriptor,client_message,n,0, (struct sockaddr *)&newSocketInfo->addr, newSocketInfo->size);

        if(n==0) {
            puts("Client Disconnected");
        } else if (n > 0) {
            puts("recvfrom ok");
        } else {
            perror("read failed");
        }
        sleep(1);
    }
    return 0;
}

提前致谢

0 个答案:

没有答案