ソケットでポート監視

やっとこさ本来の目的だったソケットに到着しました。

購入したのはもうずいぶんと前で、飲み会の時間つぶしに本屋さんに行ったときにおぉぉと思って買っておいた、TCP/IP Sockets in Cという本を翻訳したTCP/IPソケットプログラミングC言語編という書籍です。

サンプルコードを書きながら何をやっているかもわかるようになって、やっとこさってとこですね。最初はTCPのエコークライアント/サーバーですが、サンプルだけも面白くないので、ちょっと逸れてポート監視にしてみました。

ソース 4.29 インデントがおかしかったので修正

#include <stdio.h>                      // printf, fprintf, perror
#include <netinet/in.h>         // IPPROTO_TCP
#include <sys/socket.h>         // socket, connect, send, recv
#include <arpa/inet.h>          // sockaddr_in, inet_addr
#include <stdlib.h>                     // atoi
#include <string.h>                     // memset
#include <unistd.h>                     // close
#include <time.h>

#define RCVBUFSIZE 32
#define CheckPortNUM 6

void DieWithError(char *errorMessage)           // エラー処理
{
   perror(errorMessage);
   exit(1);
}

int main(int argc, char *argv[])
{
   int sock;               // ソケットディスクリプタ
   struct sockaddr_in ServAddr;    //サーバのアドレス
   int i = 0;
   int ServPort[CheckPortNUM] = {22, 25, 80, 110, 443, 995};
               // チェックしたい対象ポート
   int ChPort;             //代入の為のクッション変数
   char *servIP;                                           // サーバのIPアドレス

   if((argc < 2 || argc >= 3))
   {
     fprintf(stderr, "Usage: %s <server IP><Echo Word>[<Echo Port>]\n",
                       argv[0]);
     return 1;
   }
   servIP = argv[1];               // IPアドレスを取る

   /* ポート以外のサーバのアドレス構造体を作成 */
   memset(&ServAddr, 0, sizeof(ServAddr));         //0で埋める
   ServAddr.sin_family = AF_INET;                                  //アドレスファミリ
   ServAddr.sin_addr.s_addr = inet_addr(servIP);   // IPアドレス

     while(i < CheckPortNUM){
     /* TCPソケットを作成 */
     if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
       DieWithError("sokcet() failed");

     ChPort = ServPort[i];
     ServAddr.sin_port = htons(ChPort);              //ポート番号
     /*・サーバへの接続を確立する。*/
     if(connect(sock, (struct sockaddr *)&ServAddr, sizeof(ServAddr)) == 0)
       printf("%d Port OK\n", ChPort); //戻り値が0ならListen
     else
       printf("%d Port NG\n", ChPort);
     i++;
     close(sock);
     }

   return 0;
}

結果 複数

% ./TCPPortCheck 127.0.0.1
22 Port OK
25 Port OK
80 Port NG
110 Port NG
443 Port NG
995 Port NG

$ ./TCPPortCheck 127.0.0.1
22 Port NG
25 Port OK
80 Port OK
110 Port NG
443 Port NG
995 Port NG
10022 Port OK
486 Port NG

名前解決もできないしタイムアウトもないので、プログラムに求められる・・・なんだっけ。何か忘れてしまったけど、使い道は広くはない。たとえば、何回か続けて同じポートでNGが出たらメール送信する!とかすれば使える感じかなぁ。

今使っている本番サーバーではシェルスクリプトで80番をGETしてステータスコードが200じゃなければreloadするという監視スクリプトが動いていますが、よく見れば今回作ったプログラムの方が色々と広げられそうですね。

使えるのか使えないのかどっちなんだ(笑)
まあいい。

この書籍ですが、学生向けの教科書らしく説明はかなり丁寧で、いままでの復習にもなるし、さらに詳しく知る事もできるようなものになっています。

まだ読みだしたとこですけど、今までブックマークしているウェブサイトとかも合わせて進めたいと思います。

また何か作ろう。

参考文献

TCP/IP ソケットプログラミングC言語編
小高知宏訳 Michael J. Donahoo/Kenneth L. Calvert共著