ポート番号について


  1. ポート番号とは
  2. 予約済みポート番号
  3. 短命ポート番号
  4. ポート番号情報
  5. 割り当て済みポート番号情報

ポート番号とは

TCP/IP および UDP プロトコルでは、 クライアント・プロセスがサーバ・プロセスと接続するためには、 そのサーバを識別するための Internet アドレス (IP) を知る必要があります。 さらにそのサーバ上のどのプロセスかを識別するためにポート番号を使いますが、 ほとんどのものは IANA (Internet Assigned Numbera Authority) に登録することが必要です。

ポート番号は 16 ビットで、0 から 65535 まで可能です。

ポート番号 説          明
0-1023 well-known port と呼ばれ予約済みです。
IANA が管理しています。
1024-49151 registerd port と呼ばれ様々なアプリで使用する機能がまとめられています。
IANA が管理しています。
49152-65535 dynamic port と呼ばれユーザが任意に使用できます




予約済みポート番号

1 から 1023 までは、システムでスーパユーザのために予約済みです (well-known port)。 たとえば、FTP (File Transfer Protocol) には、21 が割り当てられています。

短命ポート番号

TCP や UDP がユーザ・プロセスに対して自動的に割り当てるポート番号は、 短命ポート番号 (ephemeral port number) と呼ばれます。

それは solaris では、32768 から 65535 ですが、 Linux では 1024 以上の空きポートをすべて使うようです。

ポート番号ゼロで bind 要求すると、この動作を選択できます。




ポート番号情報

unix では、これらの情報を /etc/services に書くことになっていますが、 書かなくても使うことはできます。 netstat -a で表示したとき、/etc/services に書かれているポート番号は、 サービス名で表示されます。 ポート番号をそのまま数字で表示したい場合は、-an オプションを使います。

使いたいポート番号が、すでに使われているかどうかを知るには、 以下のコマンドが利用できます。

netstat -an |grep PORT_NUMBER

これでなにも出なければ、そのポートは利用可能です。 また、ローカルアドレスのカラムがポート番号と同じでなければ、 その行は無視できます。

portstat [-tuh] [MIN_PORT [,MAX_PORT]]  (osaka:/export/home6/taka/cc)

  > portstat 13110 13120

  Port Services   tcp Status    : Reason           Services=/etc/services
------ ---------- --------------------------------------
 13110 istagent   Available
 13111            Available
 13112            Available
 13113            Available
 13114            Available
 13115 istsrv     Available
 13116            Not available : Address already in use
 13117            Available
 13118            Available
 13119            Available
 13120 istjobs    Available

portstat のソース・コードは以下のとおりです。

/*
    Function : get port informations of TCP/IP or UDP
    Usage    : portstat [-htu] [MIN_PORT [MAX_PORT]]
    OutFormat: port_number:service_name status
    Info     : port number is 16bits info (u_short)
               1 .. 255  system reserved (well-known port)
               1 .. 1023 reserved for super user (4.3BSD)
    Warn     : if you want to get informations of port 1~1023,
               you must be super user
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

extern int errno;
extern int optind,opterr,optopt;
extern char *optarg;
void   usage();

#define SZ_ADDR   (sizeof(struct sockaddr_in))
#define MIN_PORT   1
#define MAX_PORT   0xffff
#define FR_PORT    0
#define TO_PORT    1

char  *pname;
char  tcpID[]="tcp",udpID[]="udp";
char  sp[]=" ";

int main(int argc,char *argv[]) {
   int                i,sockfd,ret,c,protocol,sock_type;
   int                fr_port=MIN_PORT,to_port=MAX_PORT;
   int                tmp[2];
   struct sockaddr_in addr;
   struct servent     *sent;
   char               *emsg,*cp,*proto;

/* 
   check input parameters   
 */
/* . set defaults           */
   pname     = argv[0];
   proto     = tcpID;
   protocol  = IPPROTO_TCP;
   sock_type = SOCK_STREAM;
   tmp[0]    = tmp[1] = 0;

/* . check input options           */
   while ((c=getopt(argc,argv,"htu")) != EOF)
   switch(c) {
      case 't':
         break;
      case 'u':
         proto     = udpID;
         protocol  = IPPROTO_UDP;
         sock_type = SOCK_DGRAM;
         break;
      default:
         printf("%s : Input option error\n",pname);
      case 'h':
         usage();
         exit(1);
         break;
   }
/* . check input port numbers           */
   if ((argc >= (optind+1)) && (argc <= (optind+2))) {
      for (i=0; optind<argc; optind++,i++) {
         tmp[i] = atoi(argv[optind]);
      }
      if ((tmp[FR_PORT] > 0) && (tmp[TO_PORT]<= MAX_PORT) && 
          (tmp[FR_PORT] <= tmp[TO_PORT])) {
      }
      else if (tmp[TO_PORT] == 0) {
         tmp[TO_PORT] = tmp[FR_PORT];
      }
      else goto err_msg;
   }
   else {
err_msg:
#ifdef DEBUG
      printf("argc=%d optind=%d argv=%s tmp0=%d tmp1=%d fr=%d to=%d\n",
              argc,optind,argv[optind],tmp[0],tmp[1],fr_port,to_port);
#endif
      printf("%s : Input arguments error\n",pname);
      usage();
      exit(1);
   }
/* 
   get socket informations
 */
   fr_port = tmp[FR_PORT];
   to_port = tmp[TO_PORT];
   printf("  Port Services   %s Status    : Reason           Services=/etc/services\n",
       proto);
   printf("------ ---------- --------------------------------------\n");

   for (i=fr_port; i<=to_port; i++) {
      if (( sockfd = socket(AF_INET,sock_type,protocol)) == -1) {
         perror(pname);
         exit(2);
      }
/* get service name from /etc/services  */
      sent = getservbyport(i,proto);
#ifdef DEBUG
      if (sent) printf("%s\n",sent->s_name);
#endif
/* set addr   */
      bzero((char *) &addr,SZ_ADDR);
      addr.sin_family         = AF_INET;
      addr.sin_addr.s_addr    = htonl(INADDR_LOOPBACK);
      addr.sin_port           = htons(i);
      ret = bind(sockfd,(struct sockaddr *) &addr,SZ_ADDR);
      cp  = (sent ? sent->s_name : sp);
      printf("%6d %-10s ",i,cp);
      if (ret == -1)  {
         emsg = (char *)strerror(errno);
         printf("Not available : %s\n",emsg);
      }
      else {
         printf("Available\n");
      }
      close(sockfd);
   }
}

void usage() {
   printf("  Usage: %s [-tuh] MIN_PORT MAX_PORT    (1 ~ %d)\n",pname,MAX_PORT);
   printf("      -t : TCP/IP (default)\n");
   printf("      -u : UDP\n");
   printf("      -h : help");
   printf("  Ex)    %s 1500 1550\n",pname);
}




割り当て済みポート番号情報

  1. 既知ポート番号一覧
  2. Port Number (IANA)

関連項目 (solaris)

netstat(1M),tcp(7P),udp(7P)

参考書籍

ポート番号の仕組みと活用   株式会社ディーアート  市川昭彦