我遇到了这个问题,如何在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, ðreq)==-1) {
perror("ioctl (SIOCGIFCONF) 1\n");
close(fd);
return -1;
}
ethreq.ifr_flags |= IFF_PROMISC;
if (ioctl(fd, SIOCSIFFLAGS, ðreq)==-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, ðreq); //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();
}
谢谢回复。
if(n == fd)
应该是if (events[n].data.fd == fd)