xmcxguo 发表于 2013-07-02 10:58

为什么会重复收取同一个数据包

RT 最近在学习写一个数据包转发的程序 可是在写好测试的时候发现总是会重复收发同一个数据包 比如我在一端发送一个A数据包 但是在另一端却收到了5个一模一样的A包 请教各种大神这会是什么原因造成的?

源码如下。。。不胜感激

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h> //xin hao xiang tou wen jian
#define MAX 10240


char buf_eth0;
volatile int num0,lenth0;
char buf_eth1;
volatile int num1,lenth1;
sem_t sem0,sem1,sem2,sem3;



void *recv_eth0(void* attr)
{
int *sockid;
int ret=0,recv0,i,r,old;
struct ethhdr *eth;
struct iphdr *iph;
char *px;
sockid = (int*)attr;



while(1)
        {
       sem_wait(&sem2);
       if(MAX - ret <100)
                {
               ret = 0;
                }
       recv0 = recv(*sockid,&buf_eth0,MAX-ret,0);
       
       if(recv0 == 0)
                {
               sem_post(&sem2);
               continue;
                }
       
       px = &buf_eth0;
       eth = (struct ethhdr*)px;
       iph = (struct iphdr*)(px+sizeof(struct ethhdr));
       char *s1 = inet_ntoa(*(struct in_addr *)&iph->daddr);
       char *s2 = "192.168.1.233";
       r = strcmp(s1,s2);
       if((r == 0)||(iph->protocol > 100))
                {
                  old = ret;
                       lenth0 = ret;
                 
                 num0 = recv0;
                 ret = ret + recv0;

               if((buf_eth0 == 0x2e)&&(recv0 > 70))
                        {
                       buf_eth0 = 0x12;
                         buf_eth0 = 0x34;
                         buf_eth0 = 0x56;

                        printf("==========================\n");
                        printf("%d bytes read\n",recv0);
                        for(i=old+54;i<old+recv0;i++)
                                {
                              printf(" %02x",buf_eth0);
                              if( (i+1-old-54) % 16 == 0)
                                        {
                                      printf("\n\n");                       
                                        }
                           
                                }
                       printf("\n\n");
                        }
               recv0 = 0;
               sem_post(&sem0);
                }
       else
                {
               sem_post(&sem2);
                }
               
        }

return (void*)0;
}

void *send_eth0(void* attr)
{
int *sockid;
int sem,send0;
sockid = (int*)attr;
while(1)
        {
        /*sem = sem_trywait(&sem1);
        if(sem == 0)
                {       
                //send0 = send(*sockid,&buf_eth1,num1,0);
                send0 = sendto(*sockid,&buf_eth1,num1,0,(struct sockaddr *)&ether0,sizeof(ether0));
               //send0 = send(*sockid,buf_eth1,num1,0);
                }
        else
                {
               continue;
                }
        sem_post(&sem3);*/
       sem_wait(&sem1);
               
       send0 = send(*sockid,&buf_eth1,num1,0);
        //send0 = sendto(*sockid,&buf_eth1,num1,0,(struct sockaddr *)&ether0,sizeof(ether0));
       
        sem_post(&sem3);
       
        }
return (void*)0;
}


void *recv_eth1(void* attr)
{
int *sockid;
int ret=0,recv1,r;
struct ethhdr *eth;
struct iphdr *iph;
sockid = (int*)attr;
char *px;
while(1)
        {
       sem_wait(&sem3);
       if(MAX - ret <100)
                {
               ret = 0;
                }
       recv1 = recv(*sockid,&buf_eth1,MAX-ret,0);
       
       if(recv1 == 0)
                {
               sem_post(&sem3);
               continue;
                }
       
       px = &buf_eth1;
       eth = (struct ethhdr*)px;
       iph = (struct iphdr*)(px+sizeof(struct ethhdr));
       char *s1 = inet_ntoa(*(struct in_addr *)&iph->daddr);
       char *s2 = "192.168.1.77";
       r = strcmp(s1,s2);
       if((r == 0)||(iph->protocol > 100))
                {
                  
                       lenth1 = ret;          
                 num1 = recv1;
                 ret = ret + recv1;
                  recv1 = 0;
                  sem_post(&sem1);
                }
       else
                {
               sem_post(&sem3);
                }
               
       /*recv1 = recv(*sockid,buf_eth1,MAX,0);
       num1 = recv1;
       sem_post(&sem1);*/

        }

return (void*)0;
}

void *send_eth1(void* attr)
{
int *sockid;
int sem,send1,sendnum;
sockid = (int*)attr;
while(1)
        {
        /*sem = sem_trywait(&sem0);
        if(sem == 0)
                {       
                //send1 = send(*sockid,&buf_eth0,num0,0);
                send1 = sendto(*sockid,&buf_eth0,num0,0,(struct sockaddr *)&ether1,sizeof(ether1));
               //send1 = send(*sockid,buf_eth0,num0,0);
                }
        else
                {
               continue;
                }
       sem_post(&sem2);*/

       sem_wait(&sem0);
       
       //send1 = sendto(*sockid,&buf_eth0,num0,0,(struct sockaddr *)&ether1,sizeof(ether1));       
       send1 = send(*sockid,&buf_eth0,num0,0);
       sem_post(&sem2);
        }
return (void*)0;
}



int main()
{
pthread_t thd0,thd1,thd2,thd3;
int ret,sock_recv0,sock_send0,sock_recv1,sock_send1,bindid;
struct ifreq ifr0,ifr1;
struct sockaddr_ll ether0,ether1;
int *attr;
ret = sem_init(&sem0,0,0);
ret = sem_init(&sem1,0,0);
ret = sem_init(&sem2,0,1);
ret = sem_init(&sem3,0,1);
                               /*Creat socks*/


/*eth0 recv sock*/
sock_recv0 = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sock_recv0 < 0)
        {
       printf("Creat eth0 receive socket error\n");
        }
else
        {
       printf("eth0 receive socket created\n");
        }
bzero(&ether0,sizeof(ether0));
strcpy(ifr0.ifr_name,"eth0");
ether0.sll_family = PF_PACKET;
ioctl(sock_recv0,SIOCGIFINDEX,&ifr0);
ether0.sll_ifindex = ifr0.ifr_ifindex;
ether0.sll_protocol = htons(ETH_P_ALL);
bindid = bind(sock_recv0,(struct sockaddr_ll*)&ether0,sizeof(struct sockaddr_ll));
if(bindid < 0)
        {
         printf("Bind recv socket failed\n");
       printf("%d\n",bindid);
        }
else
        {
          printf("Bind recv sock to eth0 success\n");
      }
/*eth0 send sock*/
sock_send0 = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sock_send0 < 0)
        {
       printf("Creat eth0 send socket error!\n");
        }
else
        {
       printf("eth0 send socket created\n");
        }
ioctl(sock_send0,SIOCGIFINDEX,&ifr0);
ether0.sll_ifindex = ifr0.ifr_ifindex;
bindid = bind(sock_send0,(struct sockaddr_ll*)&ether0,sizeof(struct sockaddr_ll));
if(bindid < 0)
       {
          printf("Bind send socket failed\n");
          printf("%d\n",bindid);
       }
else
       {
          printf("Bind send sock to eth0 success\n");
       }
/*eth1 recv sock*/
sock_recv1 = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sock_recv1 < 0)
        {
       printf("Creat eth1 receive socket error\n");
        }
else
        {
       printf("eth1 receive socket created\n");
        }
//x = fcntl(sock_recv1,F_GETFL,0);
//fcntl(sock_recv1,F_SETFL,x|O_NONBLOCK);
bzero(&ifr1,sizeof(ifr1));
bzero(&ether1,sizeof(ether1));
strcpy(ifr1.ifr_name,"eth1");
ether1.sll_family = PF_PACKET;
ioctl(sock_recv1,SIOCGIFINDEX,&ifr1); //get eth1 index
ether1.sll_ifindex = ifr1.ifr_ifindex;
ether1.sll_protocol = htons(ETH_P_ALL);

bindid = bind(sock_recv1,(struct sockaddr_ll*)&ether1,sizeof(struct sockaddr_ll));
if(bindid < 0)
       {
          printf("Bind recv socket failed\n");
          printf("%d\n",bindid);
        }
else
        {
          printf("Bind recv sock to eth1 success\n");
        }
/*eth1 send sock*/
sock_send1 = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sock_send1 < 0)
        {
          printf("Creat eth1 send socket error!\n");
        }
else
        {
       printf("eth1 send socket created\n");
        }
ioctl(sock_send1,SIOCGIFINDEX,&ifr1); //get eth1 index
ether1.sll_ifindex = ifr1.ifr_ifindex;
bindid = bind(sock_send1,(struct sockaddr_ll*)&ether1,sizeof(struct sockaddr_ll));
if(bindid < 0)
       {
          printf("Bind send socket failed\n");
          printf("%d\n",bindid);
       }
else
       {
          printf("Bind send sock to eth1 success\n");
       }



                        /*Creat pthreads*/
attr = &sock_recv0;
ret= pthread_create(&thd0,NULL,(void*)recv_eth0,(void*)attr);
if(ret)
        {
       printf("Creat pthread_eth0 error\n");
       exit(0);
        }
attr = &sock_send0;
ret= pthread_create(&thd1,NULL,(void*)send_eth0,(void*)attr);
if(ret)
        {
       printf("Creat pthread_eth0 error\n");
       exit(0);
        }
attr = &sock_recv1;
ret= pthread_create(&thd2,NULL,(void*)recv_eth1,(void*)attr);
if(ret)
        {
       printf("Creat pthread_eth0 error\n");
       exit(0);
        }
attr = &sock_send1;
ret= pthread_create(&thd3,NULL,(void*)send_eth1,(void*)attr);
if(ret)
        {
       printf("Creat pthread_eth0 error\n");
       exit(0);
        }
//while(1);
pthread_join(thd3,NULL);

return 0;
}

卖萌犯法 发表于 2013-07-03 11:32

这也太长了吧,看得眼都疼……

xmcxguo 发表于 2013-07-05 15:21

回复 2# 卖萌犯法


   

xmcxguo 发表于 2013-07-05 15:23

回复 2# 卖萌犯法


    我错了。。。那个如果我改了TCP报文数据段的内容,TCP报头那里的校验和要不要改?以太网帧最后四位的CRC校验码要不要改?

卖萌犯法 发表于 2013-07-07 01:27

回复 4# xmcxguo

TCP报头那里的校验和要不要改
要重新计算

以太网帧最后四位的CRC校验码要不要改
用户空间的程序不需要关心CRC,它由网卡驱动计算
页: [1]
查看完整版本: 为什么会重复收取同一个数据包