Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 16000] ファイルの概要

このコミットでは、Go言語の標準ライブラリnetパッケージ内のListenTCPおよびListenUDP関数のドキュメントが更新されています。具体的には、ワイルドカードポート(ポート番号0)の割り当てに関する説明が追加・修正され、より明確な情報が提供されています。

変更されたファイルは以下の通りです。

  • src/pkg/net/tcpsock_plan9.go
  • src/pkg/net/tcpsock_posix.go
  • src/pkg/net/udpsock_plan9.go
  • src/pkg/net/udpsock_posix.go

コミット

  • コミットハッシュ: 245dc62ca4a0dd0d9f797a6c756f0992517e56ee
  • Author: Mikio Hara mikioh.mikioh@gmail.com
  • Date: Fri Mar 29 15:06:43 2013 +0900

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/245dc62ca4a0dd0d9f797a6c756f0992517e56ee

元コミット内容

net: update documentation for ListenTCP, ListenUDP

Adds the missing wildcard port assignment description to ListenUDP.
Also updates the wildcard port description on ListenTCP.

R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/8063043

変更の背景

このコミットの背景には、Go言語のnetパッケージにおけるListenTCPおよびListenUDP関数のドキュメントの明確性向上が挙げられます。特に、ポート番号に0を指定した場合の「ワイルドカードポート割り当て」の挙動について、既存のドキュメントでは説明が不足していたり、曖昧な表現があったりしたと考えられます。

ネットワークプログラミングにおいて、特定のポートではなくOSが利用可能なポートを自動的に割り当ててほしい場合、ポート番号に0を指定することが一般的です。しかし、この挙動がドキュメントに明記されていないと、開発者は以下のような疑問や問題に直面する可能性があります。

  1. 挙動の不明確さ: ポート0が具体的にどのような意味を持つのか、OSがどのようにポートを選択するのかが不明瞭。
  2. 割り当てられたポートの取得方法: ポート0を指定した場合、実際に割り当てられたポート番号をどのように取得すればよいのかが分かりにくい。
  3. プラットフォーム間の差異: plan9posixといった異なるOS環境での挙動の違いがドキュメントでカバーされていない可能性。

このコミットは、これらの問題を解消し、開発者がListenTCPListenUDPをより正確かつ安全に利用できるよう、ドキュメントを補完・修正することを目的としています。特にListenUDPについては、ワイルドカードポートに関する記述が完全に欠落していたため、その追加が急務であったと推測されます。

前提知識の解説

TCPとUDP

  • TCP (Transmission Control Protocol): 信頼性の高いコネクション指向のプロトコルです。データの順序保証、再送制御、フロー制御などを行い、アプリケーション間で信頼性の高いデータ転送を提供します。Webブラウジング (HTTP/HTTPS)、ファイル転送 (FTP)、メール (SMTP) など、多くの一般的なインターネットサービスで利用されます。
  • UDP (User Datagram Protocol): コネクションレスで信頼性の保証がないプロトコルです。データの順序保証や再送制御を行わないため、TCPよりも高速ですが、データが失われたり、順序が入れ替わったりする可能性があります。DNS、ストリーミング、オンラインゲームなど、リアルタイム性やオーバーヘッドの低さが重視されるアプリケーションで利用されます。

Go言語のnetパッケージ

Go言語の標準ライブラリnetパッケージは、ネットワークI/Oのプリミティブを提供します。TCP/UDPソケットの作成、接続、リスニング、データの送受信など、ネットワークプログラミングに必要な機能が豊富に用意されています。

  • net.ListenTCP: 指定されたTCPアドレスでリッスンを開始し、*TCPListenerを返します。このリスナーを通じて、クライアントからのTCP接続を受け入れることができます。
  • net.ListenUDP: 指定されたUDPアドレスでリッスンを開始し、*UDPConnを返します。このコネクションを通じて、UDPパケットの送受信を行うことができます。

ワイルドカードポート (ポート番号0)

ネットワークプログラミングにおいて、ソケットをバインドする際にポート番号に0を指定することは、OSに対して「利用可能な任意のポートを割り当ててください」と要求する特別な意味を持ちます。これは「ワイルドカードポート」と呼ばれます。

アプリケーションが特定のポートに依存しない場合や、一時的な通信のためにポートが必要な場合に非常に便利です。例えば、クライアントアプリケーションがサーバーに接続する際に、自身の送信元ポートを明示的に指定する必要がない場合などに利用されます。

OSがポートを割り当てた後、アプリケーションは通常、ソケットオブジェクトのAddr()(TCPの場合)やLocalAddr()(UDPの場合)といったメソッドを呼び出すことで、実際に割り当てられたポート番号を取得できます。

Addr() / LocalAddr() メソッド

Go言語のnetパッケージにおいて、TCPListenerUDPConnなどのネットワークオブジェクトは、自身がバインドされているローカルアドレス(IPアドレスとポート番号の組み合わせ)を取得するためのメソッドを提供します。

  • TCPListener.Addr(): net.Addrインターフェースを実装したオブジェクトを返します。これを*net.TCPAddrに型アサートすることで、IPアドレスとポート番号を取得できます。
  • UDPConn.LocalAddr(): 同様にnet.Addrインターフェースを実装したオブジェクトを返します。これを*net.UDPAddrに型アサートすることで、IPアドレスとポート番号を取得できます。

これらのメソッドは、ワイルドカードポート(ポート0)を指定してソケットをバインドした場合に、OSによって動的に割り当てられた実際のポート番号を知るために不可欠です。

技術的詳細

このコミットは、Go言語のnetパッケージにおけるListenTCPListenUDP関数のドキュメントを改善することに焦点を当てています。特に、ポート番号に0を指定した場合の挙動、すなわち「ワイルドカードポート割り当て」に関する説明の明確化が主な目的です。

Go言語のnetパッケージは、異なるオペレーティングシステム(OS)に対応するために、OS固有の実装を持っています。このコミットで変更されているファイル名からもわかるように、tcpsock_plan9.goudpsock_plan9.goはPlan 9オペレーティングシステム向け、tcpsock_posix.goudpsock_posix.goはPOSIX準拠のOS(Linux, macOSなど)向けのコードです。これらのファイルには、それぞれのOS環境でのソケット操作に関する低レベルな実装が含まれていますが、ListenTCPListenUDPといった公開APIのドキュメントコメントは、通常、これらのOS固有のファイル内に直接記述されています。

変更の技術的なポイントは以下の通りです。

  1. ワイルドカードポートの挙動の明記:
    • 以前のドキュメントでは、「ポートが0の場合、利用可能なポートでリッスンする」といった表現が使われていましたが、このコミットでは「ListenTCP (または ListenUDP) が利用可能なポートを選択する」という、より能動的かつ明確な表現に修正されています。これにより、ポート選択の主体が関数自身であることが強調されます。
  2. 割り当てられたポートの取得方法の明確化:
    • ワイルドカードポートが割り当てられた後、実際にどのポートが使用されているかを知る方法は、TCPListenerAddr()メソッドやUDPConnLocalAddr()メソッドを使用することです。このコミットでは、この重要な情報がドキュメントに明示的に追加されています。これにより、開発者はポート0を使用した場合の完全なワークフローを理解しやすくなります。
  3. ListenUDPのドキュメント補完:
    • ListenUDPのドキュメントには、ワイルドカードポートに関する記述が完全に欠落していました。このコミットにより、ListenTCPと同様に、ポート0の挙動と、割り当てられたポートをLocalAddr()で取得する方法が追加されました。これは、ListenUDPを使用する開発者にとって特に重要な改善です。

これらの変更は、コードの機能自体を変更するものではなく、あくまでドキュメントの品質向上を目的としています。しかし、正確で分かりやすいドキュメントは、ライブラリの利用促進、バグの削減、開発者の生産性向上に大きく貢献するため、非常に価値のある変更と言えます。特に、ネットワークプログラミングにおけるポート割り当ては、アプリケーションのデプロイや設定において頻繁に遭遇する課題であり、その挙動が明確に記述されていることは、開発者にとって大きな助けとなります。

コアとなるコードの変更箇所

このコミットは、主にGo言語のnetパッケージ内のListenTCPListenUDP関数のドキュメントコメントを修正しています。以下に、各ファイルの変更箇所を抜粋し、その差分を示します。

src/pkg/net/tcpsock_plan9.go

--- a/src/pkg/net/tcpsock_plan9.go
+++ b/src/pkg/net/tcpsock_plan9.go
@@ -165,8 +165,8 @@ func (l *TCPListener) File() (f *os.File, err error) { return l.dup() }\n 
 // ListenTCP announces on the TCP address laddr and returns a TCP
 // listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a
 // port of 0, it means to listen on some available port.  The caller
-// can use l.Addr() to retrieve the chosen address.
+// can use the Addr method of TCPListener to retrieve the chosen address.
 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":

src/pkg/net/tcpsock_posix.go

--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -272,10 +272,10 @@ func (l *TCPListener) SetDeadline(t time.Time) error {\n // Closing l does not affect f, and closing f does not affect l.\n func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }\n \n-// ListenTCP announces on the TCP address laddr and returns a TCP listener.\n-// Net must be "tcp", "tcp4", or "tcp6".\n-// If laddr has a port of 0, it means to listen on some available port.\n-// The caller can use l.Addr() to retrieve the chosen address.\n+// ListenTCP announces on the TCP address laddr and returns a TCP\n+// listener.  Net must be "tcp", "tcp4", or "tcp6".  If laddr has a\n+// port of 0, ListenTCP will choose an available port.  The caller can\n+// use the Addr method of TCPListener to retrieve the chosen address.\n func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":

src/pkg/net/udpsock_plan9.go

--- a/src/pkg/net/udpsock_plan9.go
+++ b/src/pkg/net/udpsock_plan9.go
@@ -164,7 +164,10 @@ func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {\n }\n \n // ListenUDP listens for incoming UDP packets addressed to the local\n-// address laddr.  The returned connection c's ReadFrom and WriteTo\n+// address laddr.  Net must be "udp", "udp4", or "udp6".  If laddr has\n+// a port of 0, ListenUDP will choose an available port.\n+// The LocalAddr method of the returned UDPConn can be used to\n+// discover the port.  The returned connection's ReadFrom and WriteTo\n // methods can be used to receive and send UDP packets with per-packet\n // addressing.\n func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {

src/pkg/net/udpsock_posix.go

--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -180,10 +180,13 @@ func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, e\n 	return newUDPConn(fd), nil\n }\n \n-// ListenUDP listens for incoming UDP packets addressed to the\n-// local address laddr.  The returned connection c's ReadFrom\n-// and WriteTo methods can be used to receive and send UDP\n-// packets with per-packet addressing.\n+// ListenUDP listens for incoming UDP packets addressed to the local\n+// address laddr.  Net must be "udp", "udp4", or "udp6".  If laddr has\n+// a port of 0, ListenUDP will choose an available port.\n+// The LocalAddr method of the returned UDPConn can be used to\n+// discover the port.  The returned connection's ReadFrom and WriteTo\n+// methods can be used to receive and send UDP packets with per-packet\n+// addressing.\n func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 	switch net {
 	case "udp", "udp4", "udp6":

コアとなるコードの解説

上記の差分は、Go言語のnetパッケージにおけるListenTCPListenUDP関数のドキュメントコメントの変更を示しています。これらの変更は、関数の挙動自体を変更するものではなく、その説明をより正確かつ包括的にすることを目的としています。

ListenTCPのドキュメント変更 (tcpsock_plan9.go, tcpsock_posix.go)

変更前:

// If laddr has a port of 0, it means to listen on some available port.  The caller
// can use l.Addr() to retrieve the chosen address.

変更後:

// If laddr has a port of 0, ListenTCP will choose an available port.  The caller can
// use the Addr method of TCPListener to retrieve the chosen address.
  • 変更点:
    • "it means to listen on some available port.""ListenTCP will choose an available port." に変更されました。これにより、ポート選択の主体がListenTCP関数自身であることが明確に示されています。以前の表現はやや受動的でしたが、新しい表現はより能動的で、関数の責任を明確にしています。
    • "l.Addr()""the Addr method of TCPListener" に変更されました。これは、具体的な変数名(l)に依存せず、TCPListener型のAddrメソッドを使用するという、より一般的な説明になっています。これにより、ドキュメントの汎用性が向上し、コード例に依存しない理解を促します。

ListenUDPのドキュメント変更 (udpsock_plan9.go, udpsock_posix.go)

変更前 (udpsock_plan9.go):

// ListenUDP listens for incoming UDP packets addressed to the local
// address laddr.  The returned connection c's ReadFrom and WriteTo
// methods can be used to receive and send UDP packets with per-packet
// addressing.

変更後 (udpsock_posix.goも同様):

// ListenUDP listens for incoming UDP packets addressed to the local
// address laddr.  Net must be "udp", "udp4", or "udp6".  If laddr has
// a port of 0, ListenUDP will choose an available port.
// The LocalAddr method of the returned UDPConn can be used to
// discover the port.  The returned connection's ReadFrom and WriteTo
// methods can be used to receive and send UDP packets with per-packet
// addressing.
  • 変更点:
    • ListenUDPのドキュメントに、ListenTCPと同様のワイルドカードポートに関する説明が追加されました。
    • "Net must be "udp", "udp4", or "udp6"." という、net引数の有効な値に関する説明が追加されました。これは、関数の利用方法に関する基本的な情報であり、ドキュメントの完全性を高めます。
    • "If laddr has a port of 0, ListenUDP will choose an available port." という、ポート0の挙動に関する説明が追加されました。これは、ListenUDPのドキュメントに欠落していた重要な情報です。
    • "The LocalAddr method of the returned UDPConn can be used to discover the port." という、割り当てられたポートの取得方法に関する説明が追加されました。ListenUDP*UDPConnを返すため、LocalAddr()メソッドを使用することが適切であることが明記されています。

これらの変更は、Go言語のネットワークプログラミングにおけるベストプラクティスと、開発者が直面しうる一般的な疑問に対する回答をドキュメントに組み込むことで、APIの使いやすさと理解度を向上させています。

関連リンク

参考にした情報源リンク

  • Go言語 net パッケージ公式ドキュメント: https://pkg.go.dev/net (一般的なGo言語のnetパッケージの理解のため)
  • TCP/UDPに関する一般的なネットワークプログラミングの知識
  • ワイルドカードポートに関する一般的な知識