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 オプションを使います。
使いたいポート番号が、すでに使われているかどうかを知るには、 以下のコマンドが利用できます。
これでなにも出なければ、そのポートは利用可能です。 また、ローカルアドレスのカラムがポート番号と同じでなければ、 その行は無視できます。
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); }
![]() |
![]() |
ポート番号の仕組みと活用 株式会社ディーアート 市川昭彦