概述
在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。
空空如常
求真得真