在 C 中使用带有原始套接字的 epoll()

问题描述 投票:0回答:1

我遇到了这个问题,如何在C语言中将epoll()与Raw Socket一起使用?

我找到了几个例子,但它们都是针对 SOCK_DGRAM 和 SOCK_STREAM 而不是 SOCK_RAW。

我尝试修改这些示例,但是没有收到任何数据包并卡在 epoll_wait() 处。

有谁知道如何解决这个问题吗?

以下C代码是我的试用代码:

#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>
#include        <stddef.h>
#include        <sys/socket.h>
#include        <sys/types.h> 
#include        <netinet/in.h>
#include        <sys/epoll.h>
#include        <fcntl.h>
#include        <sys/ioctl.h>
#include        <net/if.h>
#include        <netpacket/packet.h>
#include        <linux/if_ether.h>
#include        <unistd.h>

struct ifreq            ethreq;
static struct sockaddr_ll   sll;
#define MAX_EVENTS 100
struct epoll_event ev;
int epollfd;
int fd;

int setnonblocking(int sockfd) {
    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK) == -1) {
        return -1;
    }

    return 0;
}

int SOCK_INIT(char *ifname) 
{
    if ((fd=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
        perror("br raw socket");
        return -1;
    }

    /* Set the network card in promiscuous mode */
    strncpy(ethreq.ifr_name,ifname,IFNAMSIZ-1);
    if (ioctl(fd, SIOCGIFFLAGS, &ethreq)==-1) {
        perror("ioctl (SIOCGIFCONF) 1\n");
        close(fd);
        return -1;
    }

    ethreq.ifr_flags |= IFF_PROMISC;
    if (ioctl(fd, SIOCSIFFLAGS, &ethreq)==-1) {
        perror("ioctl (SIOCGIFCONF) 2\n");
        close(fd);
        return -1;
    }

    memset(&sll, 0, sizeof(sll));
    sll.sll_family = PF_PACKET;
    sll.sll_protocol = htons(ETH_P_ALL);
    sll.sll_halen = 6;

    ioctl(fd, SIOCGIFINDEX, &ethreq); //ifr_name must be set to "eth?" ahead
    sll.sll_ifindex = ethreq.ifr_ifindex;

    printf("ifindex=%d if name = %s\n",sll.sll_ifindex, ethreq.ifr_name);
    setnonblocking(fd);

    epollfd = epoll_create(100);
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = fd;
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
        fprintf(stderr, "epoll set insertion error: fd=%d/n", fd);
        return -1;
    }
    else {
        printf("listen socket added in  epoll success /n");
    }

    return 0;
}

void sockd()
{
    int                 n,rxlen;
    struct epoll_event  events[MAX_EVENTS];
    int                 nfds;
    char                buf[1500];

    for (;;) {      
        nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
        if (nfds == -1) {
            perror("epoll_wait");
            exit(EXIT_FAILURE);
        }
        for (n = 0; n < nfds; ++n) {
             if(n == fd){
                  recvfrom(fd, buf, 1500, 0, NULL, NULL);
                  printf("%s\n", buf);
             }
        }
    }
}

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

    SOCK_INIT("eth0");
    sockd();
}

谢谢回复。

c epoll raw-sockets
1个回答
0
投票

if(n == fd)
应该是
if (events[n].data.fd == fd)

© www.soinside.com 2019 - 2024. All rights reserved.