epoll+MMAP recv
来源:互联网 发布:时间管理书籍 知乎 编辑:程序博客网 时间:2024/06/01 14:27
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* network */
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <netdb.h>
#include <linux/if.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/mman.h>
typedef unsigned char BYTE;
typedef unsigned short WORD16;
typedef unsigned int WORD32;
#define MCS_IPV_AND_LEN 0x45
#define MCS_UDP_TYPE 0x11 /* UDP 报文 */
#define MCS_ETH_MAC_LEN 6 /* MAC*/
#define MCS_ETH_TYPE 0x0800
typedef struct
{
BYTE ucDstMac[MCS_ETH_MAC_LEN]; /* Destination MAC Address */
BYTE ucSrcMac[MCS_ETH_MAC_LEN]; /* Source MAC Address */
WORD16 wPktType; /* Packet Type */
}Mcs_Eth_Hd;
typedef struct
{
BYTE ip_vl; /* ip version & header-len */
BYTE ip_tos; /* type of service */
WORD16 ip_len; /* total length */
WORD16 ip_id; /* identification */
WORD16 ip_off; /* flag & fragment offset field */
BYTE ip_ttl; /* time to live */
BYTE ip_pro; /* protocol */
WORD16 ip_cksum; /* checksum */
WORD32 ip_src; /* source address */
WORD32 ip_Dst; /* destination address */
}Mcs_Ip_Hd;
typedef struct
{
WORD16 udp_srcport; /* udp source port */
WORD16 udp_dstport; /* udp source port */
WORD16 udp_len; /* udp length */
WORD16 udp_cksum; /* udp checksum */
}Mcs_Udp_Hd;
int g_SendSockEth5 = -1;
int g_EthIndex[7];
struct tpacket_req req;
const int BUFFER_SIZE = 1024*1024*16; //16MB的缓冲区
#define PER_PACKET_SIZE 2048
int socketinit(void)
{
int Ret = -1;
struct sockaddr_ll SendAddrll = {0};
struct ifreq ifr;
req.tp_block_size = 4096;
req.tp_block_nr = BUFFER_SIZE/req.tp_block_size;
req.tp_frame_size = PER_PACKET_SIZE;
req.tp_frame_nr = BUFFER_SIZE/req.tp_frame_size;
g_SendSockEth5 = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
if(g_SendSockEth5 < 0)
{
printf("creat socke fail!\n");
return Ret;
}
Ret = setsockopt(g_SendSockEth5, SOL_PACKET, PACKET_RX_RING, (void *)&req, sizeof(req));
if(Ret<0)
{
perror("setsockopt");
return Ret;
}
SendAddrll.sll_family = PF_PACKET;
SendAddrll.sll_ifindex = if_nametoindex("eth0"); /**/
SendAddrll.sll_protocol = htons(ETH_P_IP);
if(0 > bind(g_SendSockEth5, (struct sockaddr *)&SendAddrll, sizeof(SendAddrll)))
{
close(g_SendSockEth5);
printf("bind fail\n");
return Ret;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, "eth0",IFNAMSIZ);
/* bind eth6 device
if(setsockopt(g_SendSockEth5, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr)) < 0)
{
close(g_SendSockEth5);
printf("setsockopt fail\n ");
return Ret;
}*/
return 0;
}
int q = 0;
int CallBackPacket(char *TempBuffer)
{
Mcs_Eth_Hd *rcvpktethdr = NULL;
Mcs_Ip_Hd *rcvpktiphdr = NULL;
Mcs_Udp_Hd *rcvpktudphdr = NULL;
char cIPdotdec[45] = {0};
printf("----------rcv pkts-----------\n");
/* eth
rcvpktethdr = (Mcs_Eth_Hd *)&TempBuffer[0];
printf("DstMac[%x:%x:%x:%x:%x:%x]\n",rcvpktethdr->ucDstMac[0],rcvpktethdr->ucDstMac[1],rcvpktethdr->ucDstMac[2],rcvpktethdr->ucDstMac[3],rcvpktethdr->ucDstMac[4],rcvpktethdr->ucDstMac[5]);
printf("SrcMac[%x:%x:%x:%x:%x:%x]\n",rcvpktethdr->ucSrcMac[0],rcvpktethdr->ucSrcMac[1],rcvpktethdr->ucSrcMac[2],rcvpktethdr->ucSrcMac[3],rcvpktethdr->ucSrcMac[4],rcvpktethdr->ucSrcMac[5]);
printf("PktType:0x%x\n",ntohs(rcvpktethdr->wPktType));*/
/* ip */
rcvpktiphdr = (Mcs_Ip_Hd *)(TempBuffer);
inet_ntop(AF_INET, (void *)&(rcvpktiphdr->ip_src), cIPdotdec, 40);
printf("b0 SrcIp:%s\n",cIPdotdec);
inet_ntop(AF_INET, (void *)&(rcvpktiphdr->ip_Dst), cIPdotdec, 40);
printf("b0 DstIp:%s\n",cIPdotdec);
/* udp */
rcvpktudphdr = (Mcs_Udp_Hd *)(TempBuffer+sizeof(Mcs_Ip_Hd));
printf("b0 srcPort:%d\n",ntohs(rcvpktudphdr->udp_srcport));
printf("b0 dstPort:%d\n",ntohs(rcvpktudphdr->udp_dstport));
printf("TempBuffer[1000] = %d\n",TempBuffer[1000]);
if(5500 == ntohs(rcvpktudphdr->udp_dstport))
{
q++;
}
printf("q = %d\n",q);
}
#define MAX_EVEVENTS_NUM 20
int main(int argc, char **argv)
{
struct sockaddr_ll daddrll;
int len = 0;
char TempBuffer[1600] = {0};
struct msghdr msg;
int i =0 ,j = 0;
int epfd = 0;
int nfds = 0;
struct epoll_event ep_event;
struct epoll_event ep_events[MAX_EVEVENTS_NUM];
int ret = 0;
char *buff = NULL;
int nIndex=0;
if(0 > socketinit())
{
return -1;
}
buff = (char *)mmap(0, BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, g_SendSockEth5, 0);
if(buff == MAP_FAILED)
{
perror("mmap");
return -1;
}
epfd = epoll_create(MAX_EVEVENTS_NUM); /*size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。*/
ep_event.data.fd = g_SendSockEth5;
ep_event.events = EPOLLIN;//| EPOLLET;
ret = epoll_ctl(epfd,EPOLL_CTL_ADD,g_SendSockEth5,&ep_event);
if(ret == -1)
{
printf("epoll_ctl error");
return;
}
while(1)
{
nfds = epoll_wait(epfd,ep_events,MAX_EVEVENTS_NUM,-1);/*3-前需要监听的所有socket句柄数,4- -1单一线程保证效率*/
/*maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size*/
/*参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)*/
if (nfds <= 0)
{
printf("nfds = %d\n",nfds);
continue;
}
for(i=0;i<nfds;++i)
{
if(ep_events[i].events&EPOLLIN)
{
printf("i = %d,nfds = %d\n",i,nfds);
//尽力的去处理环形缓冲区中的数据frame,直到没有数据frame了
for(j=0; j<req.tp_frame_nr; j++)
{
struct tpacket_hdr* pHead = (struct tpacket_hdr*)(buff+ nIndex*PER_PACKET_SIZE);
//XXX: 由于frame都在一个环形缓冲区中,因此如果下一个frame中没有数据了,后面的frame也就没有frame了
if(pHead->tp_status == TP_STATUS_KERNEL)
break;
//处理数据frame
CallBackPacket((char*)pHead+pHead->tp_net);
//重新设置frame的状态为TP_STATUS_KERNEL
pHead->tp_len = 0;
pHead->tp_status = TP_STATUS_KERNEL;
//更新环形缓冲区的索引,指向下一个frame
nIndex++;
nIndex%=req.tp_frame_nr;
}
}
else
printf("events error\n");
}
}
close(epfd);
close(g_SendSockEth5);
return 0;
}
#include <string.h>
#include <stdlib.h>
/* network */
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <netdb.h>
#include <linux/if.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/mman.h>
typedef unsigned char BYTE;
typedef unsigned short WORD16;
typedef unsigned int WORD32;
#define MCS_IPV_AND_LEN 0x45
#define MCS_UDP_TYPE 0x11 /* UDP 报文 */
#define MCS_ETH_MAC_LEN 6 /* MAC*/
#define MCS_ETH_TYPE 0x0800
typedef struct
{
BYTE ucDstMac[MCS_ETH_MAC_LEN]; /* Destination MAC Address */
BYTE ucSrcMac[MCS_ETH_MAC_LEN]; /* Source MAC Address */
WORD16 wPktType; /* Packet Type */
}Mcs_Eth_Hd;
typedef struct
{
BYTE ip_vl; /* ip version & header-len */
BYTE ip_tos; /* type of service */
WORD16 ip_len; /* total length */
WORD16 ip_id; /* identification */
WORD16 ip_off; /* flag & fragment offset field */
BYTE ip_ttl; /* time to live */
BYTE ip_pro; /* protocol */
WORD16 ip_cksum; /* checksum */
WORD32 ip_src; /* source address */
WORD32 ip_Dst; /* destination address */
}Mcs_Ip_Hd;
typedef struct
{
WORD16 udp_srcport; /* udp source port */
WORD16 udp_dstport; /* udp source port */
WORD16 udp_len; /* udp length */
WORD16 udp_cksum; /* udp checksum */
}Mcs_Udp_Hd;
int g_SendSockEth5 = -1;
int g_EthIndex[7];
struct tpacket_req req;
const int BUFFER_SIZE = 1024*1024*16; //16MB的缓冲区
#define PER_PACKET_SIZE 2048
int socketinit(void)
{
int Ret = -1;
struct sockaddr_ll SendAddrll = {0};
struct ifreq ifr;
req.tp_block_size = 4096;
req.tp_block_nr = BUFFER_SIZE/req.tp_block_size;
req.tp_frame_size = PER_PACKET_SIZE;
req.tp_frame_nr = BUFFER_SIZE/req.tp_frame_size;
g_SendSockEth5 = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
if(g_SendSockEth5 < 0)
{
printf("creat socke fail!\n");
return Ret;
}
Ret = setsockopt(g_SendSockEth5, SOL_PACKET, PACKET_RX_RING, (void *)&req, sizeof(req));
if(Ret<0)
{
perror("setsockopt");
return Ret;
}
SendAddrll.sll_family = PF_PACKET;
SendAddrll.sll_ifindex = if_nametoindex("eth0"); /**/
SendAddrll.sll_protocol = htons(ETH_P_IP);
if(0 > bind(g_SendSockEth5, (struct sockaddr *)&SendAddrll, sizeof(SendAddrll)))
{
close(g_SendSockEth5);
printf("bind fail\n");
return Ret;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, "eth0",IFNAMSIZ);
/* bind eth6 device
if(setsockopt(g_SendSockEth5, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr)) < 0)
{
close(g_SendSockEth5);
printf("setsockopt fail\n ");
return Ret;
}*/
return 0;
}
int q = 0;
int CallBackPacket(char *TempBuffer)
{
Mcs_Eth_Hd *rcvpktethdr = NULL;
Mcs_Ip_Hd *rcvpktiphdr = NULL;
Mcs_Udp_Hd *rcvpktudphdr = NULL;
char cIPdotdec[45] = {0};
printf("----------rcv pkts-----------\n");
/* eth
rcvpktethdr = (Mcs_Eth_Hd *)&TempBuffer[0];
printf("DstMac[%x:%x:%x:%x:%x:%x]\n",rcvpktethdr->ucDstMac[0],rcvpktethdr->ucDstMac[1],rcvpktethdr->ucDstMac[2],rcvpktethdr->ucDstMac[3],rcvpktethdr->ucDstMac[4],rcvpktethdr->ucDstMac[5]);
printf("SrcMac[%x:%x:%x:%x:%x:%x]\n",rcvpktethdr->ucSrcMac[0],rcvpktethdr->ucSrcMac[1],rcvpktethdr->ucSrcMac[2],rcvpktethdr->ucSrcMac[3],rcvpktethdr->ucSrcMac[4],rcvpktethdr->ucSrcMac[5]);
printf("PktType:0x%x\n",ntohs(rcvpktethdr->wPktType));*/
/* ip */
rcvpktiphdr = (Mcs_Ip_Hd *)(TempBuffer);
inet_ntop(AF_INET, (void *)&(rcvpktiphdr->ip_src), cIPdotdec, 40);
printf("b0 SrcIp:%s\n",cIPdotdec);
inet_ntop(AF_INET, (void *)&(rcvpktiphdr->ip_Dst), cIPdotdec, 40);
printf("b0 DstIp:%s\n",cIPdotdec);
/* udp */
rcvpktudphdr = (Mcs_Udp_Hd *)(TempBuffer+sizeof(Mcs_Ip_Hd));
printf("b0 srcPort:%d\n",ntohs(rcvpktudphdr->udp_srcport));
printf("b0 dstPort:%d\n",ntohs(rcvpktudphdr->udp_dstport));
printf("TempBuffer[1000] = %d\n",TempBuffer[1000]);
if(5500 == ntohs(rcvpktudphdr->udp_dstport))
{
q++;
}
printf("q = %d\n",q);
}
#define MAX_EVEVENTS_NUM 20
int main(int argc, char **argv)
{
struct sockaddr_ll daddrll;
int len = 0;
char TempBuffer[1600] = {0};
struct msghdr msg;
int i =0 ,j = 0;
int epfd = 0;
int nfds = 0;
struct epoll_event ep_event;
struct epoll_event ep_events[MAX_EVEVENTS_NUM];
int ret = 0;
char *buff = NULL;
int nIndex=0;
if(0 > socketinit())
{
return -1;
}
buff = (char *)mmap(0, BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, g_SendSockEth5, 0);
if(buff == MAP_FAILED)
{
perror("mmap");
return -1;
}
epfd = epoll_create(MAX_EVEVENTS_NUM); /*size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。*/
ep_event.data.fd = g_SendSockEth5;
ep_event.events = EPOLLIN;//| EPOLLET;
ret = epoll_ctl(epfd,EPOLL_CTL_ADD,g_SendSockEth5,&ep_event);
if(ret == -1)
{
printf("epoll_ctl error");
return;
}
while(1)
{
nfds = epoll_wait(epfd,ep_events,MAX_EVEVENTS_NUM,-1);/*3-前需要监听的所有socket句柄数,4- -1单一线程保证效率*/
/*maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size*/
/*参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)*/
if (nfds <= 0)
{
printf("nfds = %d\n",nfds);
continue;
}
for(i=0;i<nfds;++i)
{
if(ep_events[i].events&EPOLLIN)
{
printf("i = %d,nfds = %d\n",i,nfds);
//尽力的去处理环形缓冲区中的数据frame,直到没有数据frame了
for(j=0; j<req.tp_frame_nr; j++)
{
struct tpacket_hdr* pHead = (struct tpacket_hdr*)(buff+ nIndex*PER_PACKET_SIZE);
//XXX: 由于frame都在一个环形缓冲区中,因此如果下一个frame中没有数据了,后面的frame也就没有frame了
if(pHead->tp_status == TP_STATUS_KERNEL)
break;
//处理数据frame
CallBackPacket((char*)pHead+pHead->tp_net);
//重新设置frame的状态为TP_STATUS_KERNEL
pHead->tp_len = 0;
pHead->tp_status = TP_STATUS_KERNEL;
//更新环形缓冲区的索引,指向下一个frame
nIndex++;
nIndex%=req.tp_frame_nr;
}
}
else
printf("events error\n");
}
}
close(epfd);
close(g_SendSockEth5);
return 0;
}
- epoll+MMAP recv
- recv
- recv()
- recv()
- Recv
- recv
- recv
- mmap()
- mmap
- mmap
- mmap
- mmap
- mmap
- mmap
- mmap
- mmap
- mmap
- mmap()
- Androidpn客户端的整合
- 源码下载工具有关:git hg svn
- Google开源基于Deep Learning的word2vec工具
- MT6572平台加入呼吸灯功能——编写JNI
- 关于div布局的一个小疑惑
- epoll+MMAP recv
- java模仿顺序表
- Android_Loader/Animator
- JQuery Checked Calculator
- 单调队列 FZU 1894
- EditText自动弹出输入法问题
- UITextField防止键盘遮挡以及添加手势操作消失键盘
- 2013级C++第12周项目——函数应用
- CentOS下安装word2vec的linux教程