Linux下利用epoll实现两台机器之间的UDP传输丢包统计

来源:互联网 发布:javascript脚本和图片 编辑:程序博客网 时间:2024/06/05 18:42

公司机房到阿里云的数据传输有时候会出现丢包,所以需要程序来进行查询和排查,公司前辈写了一个程序来进行机器之间的丢包统计。
服务器:pong.cpp

#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <netinet/in.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define MAXLINE 1500#define SERV_PORT 2019    //服务器端口号void do_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen){    int n, jzq_num = 0;    socklen_t len;    char mesg[MAXLINE];    int i ;    for(;;)    {        len = clilen;        /* waiting for receive data */        n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);        mesg[n]=0;        printf("recvfrom data:%d %d\n",n, ++jzq_num);        printf("%s\n",mesg);        /* sent data back to client */        sendto(sockfd, mesg, n, 0, pcliaddr, len);    }}int main(int argc,char *argv[]){    int sockfd;    int m_port = SERV_PORT;    int result, buf_len;    int len = sizeof (buf_len);    struct sockaddr_in servaddr, cliaddr;    if (argc >=2) sscanf(argv[1],"%d",&m_port);    sockfd = socket(AF_INET, SOCK_DGRAM, 0); /* create a socket */    /* init servaddr */    bzero(&servaddr, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    servaddr.sin_port = htons(m_port);    printf("port:%d\n", m_port);    result = getsockopt((unsigned int)sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_len, (socklen_t *)&len);    printf ("one:getsock_recvbuf-> result:%s buf_len:%d\n", result?"NO":"YES", buf_len);    if(result == 0 && buf_len < 1024*1024)    {        buf_len = 1024*1024;        setsockopt((unsigned int)sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_len, len);  //接收缓冲区大小为1MB        printf ("setsock_recvbuf-> result:%s buf_len:%d\n", result?"NO":"YES", buf_len);        result = getsockopt((unsigned int)sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_len, (socklen_t *)&len);        printf ("two:getsock_recvbuf-> result:%s buf_len:%d\n", result?"NO":"YES", buf_len);    }    /* bind address and port to socket */    if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)    {        perror("bind error");        exit(1);    }    printf("UPD servese is bind success and do_echo now\n");    do_echo(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr));    return 0;}

测试程序check.cpp

#include <netinet/in.h>#include <sys/socket.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/epoll.h>#include <time.h>#include <unistd.h>#include <sys/types.h>#include <arpa/inet.h>#include <sys/time.h>#define MAXSIZE     1024#define FDSIZE      1024#define EPOLLEVENTS 20#define SERV_PORT   (9999)//你需要连接的服务器端口号#define LOCAL_PORT  (0)    //UDP传输端口,0表示系统分配#define WAIT_TIME   (100)static int handle_connection(int sockfd, struct sockaddr_in *servaddr, int flag);static int handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf, struct sockaddr_in *servaddr);static int do_read(int epollfd,int fd,int sockfd,char *buf, struct sockaddr_in *servaddr);static void add_event(int epollfd,int fd,int state);static void delete_event(int epollfd,int fd,int state);static void modify_event(int epollfd,int fd,int state);char send_buf[MAXSIZE];char ip[50];int check(char *ip, int port, int flag){    int sockfd;    struct sockaddr_in  servaddr;    struct sockaddr_in  clientaddr;    int res ;    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);    bzero(&servaddr,sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(port);    servaddr.sin_addr.s_addr = inet_addr(ip);    bzero(&clientaddr, sizeof(clientaddr));    clientaddr.sin_family = AF_INET;    clientaddr.sin_port = htons(LOCAL_PORT);    clientaddr.sin_addr.s_addr = htonl(INADDR_ANY);    if(bind(sockfd, (struct sockaddr *)&clientaddr, sizeof(clientaddr)) == -1)     {           perror("bind error");        exit(1);    }    sockaddr_in addrMy;    memset(&addrMy,0,sizeof(addrMy));    int leng = sizeof(addrMy);    if (getsockname(sockfd, (sockaddr*)&addrMy, (socklen_t*)&leng) != 0)    {       puts("Getsockname Error!");       return 0;    }    printf("Current Socket PORT->%d ",ntohs(addrMy.sin_port));     fflush(stdout);    res = handle_connection(sockfd, &servaddr, flag);    close(sockfd);    return res;}void print_cur_time(){     time_t timep;     struct tm *p;     time(&timep);     p = localtime(&timep); //取得当地时间     printf ("%d-%02d-%02d %02d:%02d:%02d ",(1900+p->tm_year), (1+p->tm_mon), p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);     fflush(stdout);}int main(int argc,char *argv[]){  FILE *fp;  int num = 0, lost_num = 0;  while(1)  {    fp = fopen("./home/jzq/Check/poxy.txt*/", "r");//自己创目录文件,poxy.txt里是要连的ip地址    if(fp == NULL)    {        printf("The poxy.txt not exit\n");       return 0;    }    while(~fscanf(fp, "%s", ip))    {        print_cur_time();        printf("ALY -> %s ", ip);        fflush(stdout);        check(ip, SERV_PORT, 2);        sleep(0.1);    }    fclose(fp);  }  return 0;}static int handle_connection(int sockfd, struct sockaddr_in *servaddr, int flag){    int epollfd;    struct epoll_event events[EPOLLEVENTS];    int ret, len, num = 30;    int lost_num =0;    epollfd = epoll_create(FDSIZE);    add_event(epollfd,sockfd,EPOLLIN);    while(num--)    {        len = 20;              //包长,可以按需要增大,但要注意传输时间要相应增大        memset(send_buf, '6', len);        send_buf[len] = 0;        if(sendto(sockfd, send_buf, len, 0, (struct sockaddr*)servaddr, sizeof(struct sockaddr_in)) <= 0)    {        printf("sendto error");        continue;    }        ret = epoll_wait(epollfd, events, epollevents, wait_time);        if(ret > 0 && (len = handle_events(epollfd, events, ret, sockfd, send_buf, servaddr)) > 0)    {            if(!len)                printf("unkonw\n");    }    else        {            lost_num++;             printf(".");            fflush(stdout);        }    }    close(epollfd);    printf("lost:%d%\n", lost_num*100/30);    return lost_num;}static int handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf, struct sockaddr_in *servaddr){    int fd;    int i;    for (i = 0;i < num;i++)    {        fd = events[i].data.fd;        if ((events[i].events & EPOLLIN) && (fd == sockfd))            return do_read(epollfd,fd,sockfd,buf, servaddr);    }    return -1;}static int do_read(int epollfd,int fd,int sockfd,char *buf, struct sockaddr_in *servaddr){    socklen_t len = sizeof(struct sockaddr_in);    return recvfrom(sockfd, buf, MAXSIZE, MSG_DONTWAIT, (struct sockaddr *)servaddr, &len);}static void add_event(int epollfd,int fd,int state){    struct epoll_event ev;    ev.events = state;    ev.data.fd = fd;    epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev);}static void delete_event(int epollfd,int fd,int state){    struct epoll_event ev;    ev.events = state;    ev.data.fd = fd;    epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev);}static void modify_event(int epollfd,int fd,int state){    struct epoll_event ev;    ev.events = state;    ev.data.fd = fd;    epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev);}
原创粉丝点击