ポート番号の取得方法

今回も簡単な WinSock プログラムを作って、WinSock に慣れましょう。 今回紹介するのは、プロトコル名を渡してそのプロトコルの待ち受け TCP ポート番号を返すプログラムです。 例えば、HTTP を渡すとポート番号 80 番が返ってきます。

ポート番号の取得は、getservbyname 関数で行います。サービス名を文字列で渡すと、 そのサービス名に対するポート番号を返します。戻り値は servent 型のポインタとして返され、 WinSock により割り当てられたメモリ領域をポイントします。このメモリ領域はスレッド毎にただひとつ 割り当てられた (WinSock が使いまわす) 領域をポイントしているので、これを解放したり、 プログラムから直接書き換えたりしてはいけません。

ちなみに、servent 型は次の形をしています。

typedef struct servent {  
	char FAR *s_name;  
	char FAR  FAR **s_aliases;  
	short s_port;  
	char FAR *s_proto;
} SERVENT,  *PSERVENT,  FAR *LPSERVENT;

ポート番号は short 型の s_port に返されます。これはネットワークバイトオーダーで返ってくるので、 ホストバイトオーダーに変換しないといけません。そのために、ntohs 関数を使っています。

尚、どのサービス名のポート番号を取得できるか、ということですが、これは %SYSTEMROOT%\System32\drivers\etc\services に書いてあります。 getservbyname 関数はこのファイル services を参照しています。

今回作成するプログラムの実行例は次の通りです。

> getport http
Port: 80

サンプルコード

getport.cpp として以下の内容を保存します。

#include <stdio.h>
#include <winsock2.h>

int main(int argc, char* argv[]) {

     INT rc;
     WSADATA wsaData;

     if ( 2 != argc ) {
          printf ("getport \nex. getport http\n");
          return 1;
     }

     // WinSock の初期化

     rc = WSAStartup(MAKEWORD(2, 2), &wsaData);

     if(0 != rc) {
          printf("WSAStartup Failed.\n");
          return 1;
     }

     servent* pServEnt = getservbyname ( argv[1], NULL);

     if ( pServEnt ) {
          printf ("Port: %d\n", ntohs(pServEnt->s_port));
     }
     
     // WinSock のクリーンアップ

     WSACleanup();
          
     return 0;
}

makefile は次の通りです。

TARGETNAME=getport
CPP=cl.exe
LINK32=link.exe
OUTDIR=.\chk

ALL : "$(OUTDIR)\$(TARGETNAME).exe"


"$(OUTDIR)" :
    @if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"


CPP_PROJ=\
	/MT\
	/W4\
	/Fo"$(OUTDIR)\\"\
	/Fd"$(OUTDIR)\\"\
	/c\
	/Zi\
	/DWIN32\
	/DUNICODE\
	/D_UNICODE\
		

LINK32_FLAGS=\
	ws2_32.lib\
	/subsystem:console\
	/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
	/machine:I386\
	/out:"$(OUTDIR)\$(TARGETNAME).exe"\
	/DEBUG\
	/RELEASE
	

LINK32_OBJS= \
	"$(OUTDIR)\$(TARGETNAME).obj"


"$(OUTDIR)\$(TARGETNAME).exe" : "$(OUTDIR)" $(LINK32_OBJS)
    $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)


.cpp{$(OUTDIR)}.obj::
   $(CPP) $(CPP_PROJ) $< 

上記ファイルを同じディレクトリにおき、nmake すると、 サブディレクトリ chk に実行可能ファイル getport.exe が作成されます。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説