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類的邏輯。

  1. CepollIcmp類封裝了epoll的基本操作,包括epoll的創建,添加事件,監聽循環等操作。
  2. CepollIcmp類封裝了icmp的收發包操作,包括icmp的封包,發送,收包,解包等操作。
  3. 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。

 


 

空空如常

求真得真

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM