epoll实现快速ping
概述
在VOIP的运营过程中,最常见的一类问题就是语音质量问题,网络间的丢包、延迟、抖动都会造成语音质量的体验下降。
当现网出现语音质量问题的时候,我们有没有工具能够快速的界定问题的边界,缩小排查的范围,是运营过程中的重要环节。
ping是我们查看网络状况最常用的工具,简单好用,但是也有很多限制,比如发包间隔等。
VOIP常见的媒体格式G711的发包间隔为20ms,单包大小在210字节左右.
作为C/C++开发,epoll也是我们必点的技能点。
所以,干脆自己用epoll开发一个没有限制的ping包检测工具,一举多得。
需求功能点:类ping工具,没有发包间隔限制,可以设定包大小,网络模型使用epoll实现。
环境
centos:CentOS release 7.0 (Final)或以上版本
GCC:4.8.5
代码
完整的源代码在我的git库,可以直接下载查看。现在git访问失败严重,多试几次。
源代码树型结构如下。
git clone https://github.com/yuyoucuobei/epollicmp tree epollicmp/ epollicmp/ ├── makefile ├── README.md └── src ├── define.h ├── epollicmp.cpp ├── epollicmp.h └── main.cpp
结构比较简单,根目录下是编译用的makefile,src目录下是全部的源代码文件,包括结构体定义的define.h文件,主要的业务逻辑类CEpollIcmp所在的epollicmp.h和epollicmp.cpp文件,以及程序入口的main.cpp文件。
简单讲一下CEpollIcmp类的逻辑。
- CepollIcmp类封装了epoll的基本操作,包括epoll的创建,添加事件,监听循环等操作。
- CepollIcmp类封装了icmp的收发包操作,包括icmp的封包,发送,收包,解包等操作。
- CepollIcmp类封装了消息包的缓存和统计操作,包括请求包的缓存,响应包的时间计算,响应时间的极值统计和均值统计等。
epollicmp.h文件内容:
#pragma once #include "define.h" class CEpollIcmp { public: CEpollIcmp(); ~CEpollIcmp(); int start(const string &remote_ip, int interval=DEFAULT_INTERVAL, int pkglen=DEFAULT_PKGLEN); int stop(); private: int initSock(); int mainLoop(); static void *thread_func_send_icmp(void *argv); //checksum unsigned short cal_chksum(unsigned short *addr,int len); struct timeval cal_time_offset(struct timeval begin, struct timeval end); void icmp_pack(struct icmp* icmphdr, int seq, int length); int icmp_unpack(char* buf, int len); int set_nonblock(int sockfd); void statistic_print(); private: string m_strRemoteIp; int m_iInterval; //microseconds int m_iPkgLen; int m_iEpollFd; int m_iSocketIcmp; bool m_bContinue; sockaddr_in m_addrDest; pthread_t m_threadidSend; int m_iSendCount; int m_iRecvCount; struct timeval m_tStarttime; struct timeval m_tEndtime; float m_fRespMax; float m_fRespMin; float m_fRespAll; map<int, PACKET_STATUS*> m_mapPacketStatus; mutex m_mtxMap; };
现在再回来重看代码,从设计的角度看,应该再对CEpollIcmp类的三个主要功能拆分成3个类,分别是epoll操作类,icmp包操作类和统计类,再通过一个业务逻辑类把它们组织起来。
编译
获取完整的源代码后,进入根目录,直接使用make编译
cd epollicmp make ##########COMPILE /root/zr/epollicmp/src/epollicmp.cpp########## g++ -g -Wall -O0 -std=c++11 -I/root/zr/epollicmp/src/ -c /root/zr/epollicmp/src/epollicmp.cpp -o /root/zr/epollicmp/src/epollicmp.o ##########COMPILE /root/zr/epollicmp/src/main.cpp########## g++ -g -Wall -O0 -std=c++11 -I/root/zr/epollicmp/src/ -c /root/zr/epollicmp/src/main.cpp -o /root/zr/epollicmp/src/main.o ##########LINK epollicmp########## g++ -g -Wall -O0 -std=c++11 -L./libs -lpthread -lrt -lm -I/root/zr/epollicmp/src/ /root/zr/epollicmp/src/epollicmp.o /root/zr/epollicmp/src/main.o -o epollicmp ##########COMPILE OVER##########
在根目录下可以看到编译好的epollicmp文件
-rwxr-xr-x. 1 root root 199864 9月 24 11:07 epollicmp
测试
直接执行文件epollicmp,可以看到使用方法
./epollicmp USAGE: ./epollicmp destaddr(url/ip) icmp_interval(ms) icmp_pkglen(byte)
使用 CTRL+C 停止程序
测试本地服务器到局域网的网络状况
./epollicmp 192.168.0.110 20 200 epollicmp start 192.168.0.110 20 200 CEpollIcmp::start start CEpollIcmp::initSock start PING 192.168.0.110, (192.168.0.110) (200) bytes of data every (20) microsecond. CEpollIcmp::mainLoop start 200 bytes from 192.168.0.110: icmp_seq=1 ttl=128 rtt=3.099 ms ... 200 bytes from 192.168.0.110: icmp_seq=522 ttl=128 rtt=0.369 ms ^CCEpollIcmp::stop start CEpollIcmp::mainLoop end PING 192.168.0.110, (192.168.0.110) (200) bytes of data every (20) microsecond. STATISTIC: ping duration:10.515 second send count:522 recv count:522 lose rate:0.00% resp min:0.328 ms resp max:4.350 ms resp average:1.026 ms epollicmp end
测试本地服务器到baidu的网络状况
./epollicmp www.baidu.com 20 200 epollicmp start www.baidu.com 20 200 CEpollIcmp::start start CEpollIcmp::initSock start PING www.baidu.com, (14.215.177.39) (200) bytes of data every (20) microsecond. CEpollIcmp::mainLoop start 200 bytes from 14.215.177.39: icmp_seq=1 ttl=55 rtt=6.692 ms ... 200 bytes from 14.215.177.39: icmp_seq=1028 ttl=55 rtt=6.884 ms ^CCEpollIcmp::stop start CEpollIcmp::mainLoop end PING www.baidu.com, (14.215.177.39) (200) bytes of data every (20) microsecond. STATISTIC: ping duration:20.723 second send count:1029 recv count:1029 lose rate:0.00% resp min:5.496 ms resp max:13.125 ms resp average:6.752 ms epollicmp end
总结
完整的源代码在我的git库,https://github.com/yuyoucuobei/epollicmp
本文使用epoll实现一个简单的ping工具,对epoll的基本使用方法和icmp包的收发包有一定的参考价值。
学习最好的办法还是亲自动手试试,just do it。
空空如常
求真得真