⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exp2_rip2.c

📁 实现网络层rip协议(距离矢量路由算法)
💻 C
字号:
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<net/if.h>
#include<time.h>
#include<unistd.h>
#include<signal.h>

#define KEY 1234
#define SIZE 1024
#define PORT 520
#define INIT_TIMER 5
#define SELECT_TIMER 3
#define TIMEOUT 10
#define MAX_NUM 50
typedef enum{NOTHING,REQUEST,RESPONSE} Command_Type;

struct ROUTE_ENTRY
{
    unsigned short addrFamilyId;    // Address Family Identifier(2)
    unsigned short beZero1;         // Must Be Zero(2)
    struct in_addr ipv4Addr;        // IPv4 Address(4)
    unsigned int beZero2;           // Must Be Zero(4)
    unsigned int beZero3;           // Must Be Zero(4)
    unsigned int metric;            // Metric(4)
};

struct RIP_PACKET
{
    unsigned char command;          // Command(1)
    unsigned char version;          // Version(1)
    unsigned short beZero;          // Must Be Zero(2)
    struct ROUTE_ENTRY routeEntry[25];         // Route Entries(20*25)
}recvPacket,reqPacket,resPacket;
struct RIP_PACKET routePacket;

struct ROUTE_TABLE
{
    struct ROUTE_ENTRY routeInfo;
    int isvalid;                    // 1-valid 0-not valid
    long timer;    
    int statue;
    struct in_addr sourceIPAddr;
}routeTable[MAX_NUM];

fd_set fdSet;                       // file descriptor set
struct timeval timer;
int sock;
int routeNum;
struct sockaddr_in localSockAddr,sendSockAddr,recvSockAddr;
struct in_addr localIP;
/////////////////////////////////////////////////////////////////////////////////

int GetLocalIP()
{
    int fd;
    struct ifreq ifr;
    if((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1)
    {
        close(fd);
        return -1;   
    }
    strcpy(ifr.ifr_name, "eth0");
    if(ioctl(fd,SIOCGIFADDR,&ifr))
    {
        close(fd);
        return -1;
    }
    memcpy(&localSockAddr,&ifr.ifr_addr,sizeof(struct sockaddr_in));
    localIP = localSockAddr.sin_addr;
    printf("local IP is %s\n",inet_ntoa(localIP));
    return 1;
}

void PrintEntry(struct ROUTE_ENTRY* entry)
{
    printf("Address Family Identifier: %d\n",entry->addrFamilyId);
    printf("IPv4 Address: %s\n",inet_ntoa(entry->ipv4Addr));
    printf("Metric: %d\n",entry->metric);
    printf("\n");
}

void PrintTable()
{
    int i;
    printf("IP\t\t   AddrFamilyId\t  metric  timeout  sourceIP\n");
    for(i = 0; i < MAX_NUM; i++)
    {
	if(routeTable[i].isvalid == 1)
	{
//	    PrintEntry(&routeTable[i].routeInfo);
	    printf("%s",inet_ntoa(routeTable[i].routeInfo.ipv4Addr));
	    printf("\t   %d",ntohs(routeTable[i].routeInfo.addrFamilyId));
	    printf("\t\t   %d",ntohl(routeTable[i].routeInfo.metric));
            printf("\t     %d",routeTable[i].timer);
	    printf("       %s\n",inet_ntoa(routeTable[i].sourceIPAddr));            
        }
    }
    printf("\n");
}

void SetRouteEntry(struct ROUTE_ENTRY* routeEntry, const char* ip, 
                    unsigned short afid, unsigned int metric )
{
    routeEntry->addrFamilyId = htons(afid);
    routeEntry->metric = htonl(metric);
    inet_aton(ip,&routeEntry->ipv4Addr);
    routeEntry->beZero1 = 0;
    routeEntry->beZero2 = 0;
    routeEntry->beZero3 = 0;
}

void SetRoutePacket(struct RIP_PACKET* routePacket,Command_Type ct)
{
    routePacket->command = (int)ct;
    routePacket->version = 1;
    routePacket->beZero = 0;
}

void EntryInit()
{
    FILE* file;
    char ip[16];
    int afi,metric;
    file = fopen("1.txt","r");
    if(file == NULL)
    {
        printf("cannot open file.\n");
        return;
    }
    while(fscanf(file,"%s %d %d \n",&ip,&afi,&metric)!=EOF)
    {
        SetRouteEntry(&routeTable[routeNum].routeInfo,(const char*)ip,afi,metric);
        routeTable[routeNum].timer = TIMEOUT;
        routeTable[routeNum].isvalid = 1;
        routeTable[routeNum].statue = 0;
        routeNum++;
    }
    fclose(file);
    return;
}

void RouteInit()
{
    int i,optval=0,length,error;    
    routeNum = 0;
    // init local socket address and ip address
    GetLocalIP();
    // init route table items
    for(i = 0; i < MAX_NUM; i++)
    {
        SetRouteEntry(&routeTable[i].routeInfo,"0.0.0.0",0,0);
        routeTable[i].isvalid = 0;
        routeTable[i].timer = 0;
        routeTable[i].statue = 0;
        inet_aton("0,0,0,0",&routeTable[i].sourceIPAddr);
    }
    // init request packet
    SetRoutePacket(&reqPacket,REQUEST);
    SetRouteEntry(&reqPacket.routeEntry[0],"0.0.0.0",0,16);
    // init response packet
    SetRoutePacket(&resPacket,RESPONSE);

    recvSockAddr.sin_family = AF_INET;
    recvSockAddr.sin_port = htons(PORT);
    recvSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    sendSockAddr.sin_family = AF_INET;
    sendSockAddr.sin_port = htons(PORT);
//    inet_aton("240.255.255.255",&sendSockAddr.sin_addr);
    sendSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    EntryInit();
    sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock<0)
    {
        printf("cannot create a socket!\n");
        exit(1);
    }
    if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&optval,sizeof(int)) != 0)
    {
        printf("cannot broadcast!\n");
        close(sock);
        exit(1);
    }
    if(bind(sock,(struct sockaddr*)&recvSockAddr,sizeof(recvSockAddr))<0)
    {
        printf("cannot bind to port\n");
        close(sock);
        exit(1);
    }
    length=sizeof recvSockAddr;
    getsockname(sock,(struct sockaddr*)&recvSockAddr,&length);
    printf("Port %d is opened. Listen for packet...\n",ntohs(recvSockAddr.sin_port));

    FD_ZERO(&fdSet);
    FD_SET(sock,&fdSet);
    error = sendto(sock,&reqPacket,4+sizeof(struct ROUTE_ENTRY),0,(struct sockaddr*)(&sendSockAddr),sizeof(struct sockaddr));
    if(error<0)
    {
        PrintEntry(&reqPacket.routeEntry[0]);
        printf("broadcast request packet failed! %d,%d,%d\n",error,sock,fdSet);
    }
}    

void CheckTimer()
{
    int i;
    for(i = 0; i < MAX_NUM; i++)
    {
        if(routeTable[i].isvalid == 1 && routeTable[i].statue == 0)
        {
            routeTable[i].timer--;
            if(routeTable[i].timer == 0)
                routeTable[i].statue = 1;
        }
        else continue;
    }
}

void Handler()
{
    int i=0,j=0;
    printf("Timeout for waiting, now broadcast route information!\n");
 check_info:
    for(j=0;i < MAX_NUM; i++)
    {
        if(routeTable[i].isvalid == 1 && routeTable[i].statue == 0)
        {
            memcpy(&resPacket.routeEntry[j],&routeTable[i].routeInfo,sizeof(struct ROUTE_ENTRY));
            j++;
        }
        if(j == 25)
            break;
    }
    if(j == 0)
    {
        printf("None information to broadcast.\n");
        return;
    }
//    inet_aton("255.255.255.255",&sendSockAddr.sin_addr);    
//    sendSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
     sendSockAddr.sin_addr.s_addr = localSockAddr.sin_addr.s_addr;
    if(sendto(sock,&resPacket,4+j*sizeof(struct ROUTE_ENTRY),0,(struct sockaddr*)(&sendSockAddr),sizeof(sendSockAddr))<0)
    {
        printf("broadcast request packet failed!-----%d\n",j);
        return;
    }
    else
    {
	printf("broadcast %d routeInfo.\n",j);
       // int k;
       // for(k = 0; k < j; k++)
       //     PrintEntry(&resPacket+4+20*k);  
    }
    if(j == 25) goto check_info;
    return;
}

int DealRecvPacket()
{
    int length,i,j,metric;
    int addr_len;
    addr_len = sizeof(struct sockaddr_in);
    length=recvfrom(sock,&recvPacket,sizeof(recvPacket),0,(struct sockaddr*)&recvSockAddr,&addr_len);
    printf("receive a packet size of %d from %s......\n",length,inet_ntoa(recvSockAddr.sin_addr));
    if(recvSockAddr.sin_addr.s_addr == localIP.s_addr)   
      return 1;
    if((length-4)%sizeof(struct ROUTE_ENTRY) != 0)
      return 2;
    if(recvPacket.version != 1 || recvPacket.beZero != 0)
      return 3;
    struct in_addr local;
    inet_aton("127.0.0.1",&local);
    if(recvSockAddr.sin_addr.s_addr == local.s_addr)
      return 4;
    if(recvPacket.command == REQUEST)
    {
        printf("request packet received.\n");
////////////////////////////////////////////////////////////////////////////////
        printf("now send route information as response.\n");
        i = 0;
     check_info:
        for(j=0;i < MAX_NUM; i++)
        {
            if(routeTable[i].isvalid == 1 && routeTable[i].statue == 0)
            {
                memcpy(&resPacket.routeEntry[j],&routeTable[i].routeInfo,sizeof(struct ROUTE_ENTRY));
                j++;
            }
            if(j == 25)
                break;
        }
        if(j == 0)
        {
            printf("None information to broadcast.\n");
            return 5;
        }
        //inet_aton("255.255.255.255",&sendSockAddr.sin_addr);
	 sendSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        //sendSockAddr.sin_addr.s_addr = recvSockAddr.sin_addr.s_addr;
        if(sendto(sock,&resPacket,4+j*sizeof(struct ROUTE_ENTRY),0,(struct sockaddr*)(&sendSockAddr),sizeof(sendSockAddr))<0)
        {
            printf("send request packet failed!\n");
            return 6;
        }
	printf("broadcast %d routeInfo.\n",j);
        if(j == 25) goto check_info;	
////////////////////////////////////////////////////////////////////////////////
    }
    else if(recvPacket.command == RESPONSE)
    {
        printf("response packet received.\n");
        for(i = 0; i < (length-4)/sizeof(struct ROUTE_ENTRY); i++)
        {
            metric = ntohl(recvPacket.routeEntry[i].metric);
            metric++;
            if(metric>=16)continue;
            recvPacket.routeEntry[i].metric = htonl(metric);
            for(j = 0; j < MAX_NUM; j++)
            {
                if(routeTable[j].isvalid != 1)continue;
                if(routeTable[j].routeInfo.ipv4Addr.s_addr==
                    recvPacket.routeEntry[i].ipv4Addr.s_addr)
                {
                    if(routeTable[j].sourceIPAddr.s_addr==
                        recvSockAddr.sin_addr.s_addr)
                    {
                        routeTable[j].timer = TIMEOUT;
                        routeTable[j].statue = 0;
 			routeTable[j].isvalid = 1;
                        memcpy(&routeTable[j].routeInfo,&recvPacket.routeEntry[i],sizeof(struct ROUTE_ENTRY));
                        printf("modify old routeEntry.\n");
                        break;
                    }
                    if(routeTable[j].routeInfo.metric < recvPacket.routeEntry[i].metric)
                    {
                        routeTable[j].timer = TIMEOUT;
                        routeTable[j].statue = 0;
			routeTable[j].isvalid = 1;
                        routeTable[j].sourceIPAddr.s_addr = recvSockAddr.sin_addr.s_addr;
                        memcpy(&routeTable[j].routeInfo,&recvPacket.routeEntry[i],sizeof(struct ROUTE_ENTRY));
                        printf("modify new metric and sourceIP.\n");
                        break;
                    }
                    printf("nothing to be modified.\n");
                    break;
                }
            }
            // add new routeEntry
            if(j == MAX_NUM)
            {
                j=0;
                while(routeTable[j].isvalid == 1)
                    j++;
                routeNum++;
                routeTable[j].isvalid = 1;
                routeTable[j].timer = TIMEOUT;
                routeTable[j].statue = 0;
                routeTable[j].sourceIPAddr.s_addr = recvSockAddr.sin_addr.s_addr;
                memcpy(&routeTable[j].routeInfo,&recvPacket.routeEntry[i],sizeof(struct ROUTE_ENTRY));
                printf("add a new routeEntry.\n");
            }
        }
    }
    else
    {
        printf("command invalid.\n");
        return 7;
    }
    PrintTable();
    printf(" the number of route entry is %d.\n",routeNum);
    return 0;
}

main()
{
    int temp,shmid;
    int* shmNum;
    int signalNum;
    struct shmid_ds buf;
    RouteInit();

    shmid = shmget(KEY,SIZE,IPC_CREAT | 0600);
    shmNum = (int*)shmat(shmid,NULL,0);
    *shmNum = 0;
    signalNum = 0;
    shmdt(shmNum);


    if(fork() == 0)
    {
        while(1)
        {
            //signal(SIGALRM,Handler);
            temp = (int)(drand48()*10);
            sleep(temp+INIT_TIMER);
// 	    sleep(10);
            //alarm(INIT_TIMER);
            //pause();
	    shmNum = (int*)shmat(shmid,NULL,0);
//		printf("........%d\n",*((int*)shmat(shmid,NULL,0)));
	    (int)*(shmNum) = (int)*(shmNum) + 1;
            shmdt(shmNum);
            //CheckTimer();
        }
    }
    else
    {
        timer.tv_sec=SELECT_TIMER;
        timer.tv_usec=0;
        while(1)
        {
            FD_ZERO(&fdSet);                            // clears a file descriptor set
            FD_SET(sock,&fdSet);                     // adds fd to the set
            if(select(sock+1,&fdSet,NULL,NULL,&timer)<0)  // ignore writefds and exceptfds
            {
                printf("cannot select readfds!\n");
            }
            if (FD_ISSET(sock, &fdSet))
            {
                //printf("receive a route packet.\n");
                printf("deal type: -------- %d -------\n",DealRecvPacket());
            }
 		  sleep(1);
            shmctl(shmid,IPC_STAT,&buf);
            shmNum = (int*)shmat(shmid,NULL,0);
            if(signalNum != *(shmNum))
	    {
		signalNum =  *(shmNum);
                CheckTimer();
                Handler();
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -