サンプル集  >  LinuxC  >  多重ping
多重ping
2016/09/25

ホストとIPが記載されたcsvファイルを読み込み、pingを複数スレッドで実行して結果を標準出力に出力します。

◆環境
OS debian 8.2
Linux TSV01 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1+deb8u3 (2015-08-04) x86_64 GNU/Linux
gcc 4.9.2 (Debian 4.9.2-10)

pingコマンドは、実行回数1回、タイムアウト5秒で実行します。

(1) pingが通った場合
# ping -c 1 -W 5 10.21.0.1
PING 10.21.0.1 (10.21.0.1) 56(84) bytes of data.
64 bytes from 10.21.0.1: icmp_seq=1 ttl=254 time=0.894 ms

--- 10.21.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.894/0.894/0.894/0.000 ms

(2) pingが通らない場合
# ping -c 1 -W 5 10.21.0.30
PING 10.21.0.30 (10.21.0.30) 56(84) bytes of data.
From 10.21.0.10 icmp_seq=1 Destination Host Unreachable

--- 10.21.0.30 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0m
s

本プログラムではpingの出力結果に「ttl=」という文字列が含まれていたら「pingが通った」と判断します。

ホストとIPが記載されたcsvファイルは、IP+,(カンマ)+ホスト名で記載します。

hostlist.txt
1: 
2: 
3: 
4: 
10.21.0.1,Gateway
10.21.0.10,Server
10.21.0.15,PC1
10.21.0.30,PC2

ホストcsvファイルを読み込むバッファを1024にしているため、それ以上のデータを記入されるとバッファオーバーフローすると思います。

実行時のパラメーターでホストcsvファイルを指定します。

# ./MultiPing hostlist.txt
Server 10.21.0.10 OK
PC1 10.21.0.15 OK
Gateway 10.21.0.1 OK
PC2 10.21.0.30 Unreachable

第2パラメーターに多重度を指定できます。 何も指定しないと10多重で処理が行われます。

# ./MultiPing hostlist.txt 2
Server 10.21.0.10 OK
Gateway 10.21.0.1 OK
PC1 10.21.0.15 OK
PC2 10.21.0.30 Unreachable

メインです。

MultiPing.c
  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
/* 2016/09/24 1.0 新規作成 */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "MultiPing.h"

int main( int argc, char** argv )
{
//    printf( "MultiPing_main start!!\n" );
    if ( argc < 2 )
    {
        printf( "MultiPing <hostlist> [<threads number>]\n" );
        exit( 1 );
    }

    int iMaxThreads = 10;
    if ( argc == 3 )
    {
        iMaxThreads = atoi( argv[2] );
    }

    int i, j;

    /* IPリストファイルを読み込む      */
    /* レイアウト:ホスト名,IPアドレス */
    FILE *fp = fopen( argv[1], "r" );
    if ( fp == NULL )
    {
        printf( "Host list not found!! %s", argv[1] );
        exit( 2 );
    }

    HostInfo hi[HOST_LIMIT];
    memset( hi, NULL, sizeof( hi ) );

    int hiCnt=0;
    for ( i = 0; ; i++ )
    {
        char  buf[HOSTNAME_LEN+IP_LEN+1];
        char *ret;

        /* ファイルを1行読み込む */
        memset( buf, 0x00, sizeof( buf ) );
        ret = fgets( buf, sizeof( buf ), fp );
        if ( ret == NULL )
        {
            break;
        }

        /* 改行コードを除去 */
        for ( j = 0; j < ( int )strlen( buf ); j++ )
        {
            if ( ( ( unsigned char )buf[j] == '\r' )
            ||   ( ( unsigned char )buf[j] == '\n' )
            )
            {
                buf[j] = NULL;
            }
        }

        /* ,で区切り構造体配列へ格納する */
        int iBufLen = strlen( buf );
        for ( j = 0; j < iBufLen; j++ )
        {
            if ( ( unsigned char )buf[j] == ',' )
            {
                memcpy( hi[i].pIP, buf, j );
                memcpy( hi[i].pHostName
                      , buf + j + 1
                      , iBufLen - j
                      );
                break;
            }
        }
        hiCnt++;
    }

    fclose( fp );

    int iRunThreads =  0;

    pthread_t *tid
    = ( pthread_t* )malloc( sizeof( pthread_t ) * iMaxThreads );

    int ret   = 0;
    int hiRun = 0;
    for ( hiRun = 0; hiRun < hiCnt; )
    {
        /* スレッドを生成 */
        iRunThreads = 0;
        for ( j = 0; j < iMaxThreads; j++ )
        {
/*
            printf( "hi:%d/%s/%s<\n"
                  , hiRun
                  , hi[hiRun].pHostName
                  , hi[hiRun].pIP
                  );
*/

            ret = pthread_create( &tid[j]
                                , NULL
                                , myThread
                                , ( void* )&hi[hiRun]
                                );
            if ( ret != 0 )
            {
                /* スレッド生成失敗 */
                printf( "pthread_create failed!!=[%d]\n", ret );
                exit( -1 );
            }
            iRunThreads++;

//            printf( "thread ID=[%ld]\n", tid[j] );

            hiRun++;
            if ( hiRun >= hiCnt )
            {
                /* HostInfoの件数(hiCnt)より実行件数(hiRun) */
                /* の方が同じか大きい場合、処理はおしまい。 */
                break;
            }
        }

        /* 生成したスレッドの数だけスレッドの終了を待つ */
        for ( j = 0; j < iRunThreads; j++ )
        {
            pthread_join( tid[j], NULL );
        }
    }

    free( tid );

//    printf( "MultiPing_main end!!\n" );

    return 0;
}

ヘッダーファイルです。

MultiPing.h
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
#define HOSTNAME_LEN   64
#define IP_LEN         13
#define HOST_LIMIT   1024

typedef struct _HostInfo {
    char pHostName[HOSTNAME_LEN+1];
    char pIP[IP_LEN+1];
} HostInfo;

extern void* myThread( void* );

スレッド処理です。

MultiPing_threadMain.c
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
74: 
/* 2016/09/24 1.0 新規作成 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#include "MultiPing.h"

/* pingコマンドの出力結果を編集する */
char* searchWord( char* pBuf )
{
    char* pos;
    pos = strstr( pBuf, "ttl=" );
    if ( pos != NULL )
    {
        return "OK\n";
    }

    return "Unreachable\n";
}

void* myThread( void* pParam )
{
//    printf( "My Thread start!!\n" );

    HostInfo* hi = ( HostInfo* )pParam;

//    printf( "hi:%s/%s<\n", hi->pHostName, hi->pIP );

    FILE* fp;

    char cmd[256];
    char buf[256];
    char buf2[256];
    memset( buf, 0x00, sizeof( buf ) );

    // pingコマンド文字列の生成
    memset( cmd, 0x00, sizeof( cmd ) );
    sprintf( cmd, "ping -c 1 -W 5 %s", hi->pIP );

    // コマンド実行
    fp = popen( cmd, "r" );
    int i = 0;
    for ( i = 0; ; i++ )
    {
        // 実行結果を読み込む
        if ( fgets( buf, 256, fp ) == NULL )
        {
            break;
        }

        if ( i != 1 )
        {
            // 2行目以外は検査しない
            continue;
        }

        char* msg = searchWord( buf );
        memset( buf2, 0x00, sizeof( buf2 ) );
        sprintf( buf2
               , "%s %s %s"
               , hi->pHostName
               , hi->pIP
               , msg
               );
        ( void )fputs( buf2, stdout );
    }
    ( void )pclose( fp );

//    printf( "My Thread end!!\n" );

    /* スレッド終了 */
    pthread_exit( 0 );
}

makefileです。

makefile
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
# 2016/09/24 (c) ymlib.com
TARGET = MultiPing
OBJS = MultiPing.o            \
       MultiPing_threadMain.o
CC = /usr/bin/gcc

$(TARGET): $(OBJS)
        $(CC) -o $@ $(OBJS) -lpthread
.SUFFIXES: .c.o
.c.o:
        $(CC) -Wall -c $< -g

clean:
        rm -f $(TARGET) $(OBJS)

▲ PageTop  ■ Home


Copyright (C) 2016 ymlib.com