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

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

このコミットは、Go言語のnetパッケージにおけるListenUnixgram関数のシグネチャを変更し、戻り値の型を*UDPConnから*UnixConnに修正するものです。これにより、Unixドメインソケットのデータグラム通信が正しく機能するようになり、ReadFromWriteToといったUnixConn固有のメソッドが利用可能になります。

コミット

commit 0d197251eedad2185a41f9fe7facb20fd5bb3061
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sun Dec 16 11:51:47 2012 +0900

    net: change ListenUnixgram signature to return UnixConn instead of UDPConn
    
    This CL breaks Go 1 API compatibility but it doesn't matter because
    previous ListenUnixgram doesn't work in any use cases, oops.
    
    The public API change is:
    -pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
    +pkg net, func ListenUnixgram(string, *UnixAddr) (*UnixConn, error)
    
    Fixes #3875.
    
    R=rsc, golang-dev, dave
    CC=golang-dev
    https://golang.org/cl/6937059

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

https://github.com/golang/go/commit/0d197251eedad2185a41f9fe7facb20fd5bb3061

元コミット内容

net: change ListenUnixgram signature to return UnixConn instead of UDPConn

この変更はGo 1のAPI互換性を破るものですが、以前のListenUnixgramはどのユースケースでも機能しなかったため問題ないとされています。

公開APIの変更点:

  • pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
  • pkg net, func ListenUnixgram(string, *UnixAddr) (*UnixConn, error)

Issue #3875を修正します。

変更の背景

このコミットの背景には、Go言語のnetパッケージにおけるListenUnixgram関数の既存の実装が、Unixドメインデータグラムソケットの本来の機能を提供できていなかったという問題があります。具体的には、ListenUnixgramはUnixドメインデータグラムソケットをリッスンするために設計されていましたが、その戻り値の型が*UDPConnとなっていました。

UDPConnはIPネットワークにおけるUDP(User Datagram Protocol)通信を扱うための型であり、Unixドメインソケットとは異なる特性を持っています。Unixドメインソケットはファイルシステム上のパスをアドレスとして使用し、プロセス間通信(IPC)に特化しています。UDPConnのメソッドはIPアドレスやポート番号を前提としているため、Unixドメインソケットの特性(例えば、ReadFromUnixWriteToUnixのようなUnixドメインソケット固有のメソッド)を直接扱うことができませんでした。

結果として、以前のListenUnixgramは、Unixドメインデータグラムソケットを確立しても、そのソケットを通じてデータグラムを送信したり、送信元アドレスを特定して受信したりするような、期待される動作ができませんでした。コミットメッセージにある「previous ListenUnixgram doesn't work in any use cases, oops.」という記述は、この機能不全を端的に示しています。

この問題を解決し、ListenUnixgramがUnixドメインデータグラムソケットとして完全に機能するようにするために、戻り値の型を*UnixConnに変更する必要がありました。UnixConnはUnixドメインソケットに特化したコネクション型であり、ReadFromUnixWriteToUnixといった、Unixドメインデータグラム通信に必要なメソッドを提供します。この変更により、ListenUnixgramは意図された通りにUnixドメインデータグラム通信をサポートできるようになります。

前提知識の解説

Unixドメインソケット (Unix Domain Sockets / UDS)

Unixドメインソケットは、同じホストマシン上で動作するプロセス間で通信を行うためのメカニズムです。TCP/IPソケットがネットワークを介した通信(異なるホスト間や同じホスト上の異なるプロセス間)に使用されるのに対し、Unixドメインソケットはファイルシステム上の特殊なファイル(ソケットファイル)を介して通信を行います。

主な特徴:

  • 高速性: ネットワークスタックを介さないため、TCP/IPソケットよりも高速なプロセス間通信が可能です。
  • セキュリティ: ファイルシステム上のパーミッションによってアクセス制御が可能です。
  • アドレス: IPアドレスやポート番号ではなく、ファイルパス(例: /tmp/my_socket)をアドレスとして使用します。
  • 種類:
    • ストリームソケット (SOCK_STREAM): TCPと同様に、信頼性のある接続指向のバイトストリーム通信を提供します。
    • データグラムソケット (SOCK_DGRAM): UDPと同様に、非接続指向のデータグラム通信を提供します。メッセージの順序や到達は保証されません。
    • シーケンシャルパケットソケット (SOCK_SEQPACKET): ストリームソケットとデータグラムソケットの中間に位置し、信頼性のある接続指向のデータグラム通信を提供します。メッセージの境界が保持され、順序も保証されます。

Go言語のnetパッケージ

Go言語の標準ライブラリであるnetパッケージは、ネットワークI/Oプリミティブを提供します。TCP/IP、UDP、Unixドメインソケットなど、様々なネットワークプロトコルを扱うためのインターフェースや型が定義されています。

  • net.Connインターフェース: ネットワーク接続の一般的なインターフェースを定義します。ReadWriteCloseLocalAddrRemoteAddrSetDeadlineなどのメソッドを持ちます。
  • net.PacketConnインターフェース: パケット指向のネットワーク接続のインターフェースを定義します。ReadFromWriteToCloseLocalAddrSetDeadlineなどのメソッドを持ちます。
  • net.UDPConn: UDPネットワーク接続を表す型です。net.PacketConnインターフェースを実装し、IPアドレスとポート番号を介したデータグラム通信に使用されます。
  • net.UnixConn: Unixドメインソケット接続を表す型です。net.Connおよびnet.PacketConnインターフェースを実装し、Unixドメインソケットを介したストリーム、データグラム、シーケンシャルパケット通信に使用されます。ReadFromUnixWriteToUnixなど、Unixドメインソケット固有のメソッドも提供します。
  • net.UnixAddr: Unixドメインソケットのアドレスを表す型です。ファイルパスとネットワークタイプ("unix""unixgram""unixpacket")を含みます。
  • net.ListenUnixgram関数: Unixドメインデータグラムソケットをリッスンするための関数です。このコミットの変更対象となっています。

ReadFromWriteToメソッド

net.PacketConnインターフェースに定義されているメソッドで、パケット指向の通信において重要です。

  • ReadFrom(b []byte) (n int, addr Addr, err error): 受信したパケットのデータをbに読み込み、そのパケットの送信元アドレスをaddrとして返します。
  • WriteTo(b []byte, addr Addr) (n int, err error): bのデータを指定されたaddrにパケットとして送信します。

これらのメソッドは、特にデータグラム通信において、どの送信元からデータが来たのか、あるいはどの宛先にデータを送るのかをパケットごとに指定・取得するために不可欠です。

技術的詳細

このコミットの核心は、net.ListenUnixgram関数の戻り値の型を*UDPConnから*UnixConnに変更した点にあります。この変更は、単なる型名の変更以上の技術的な意味合いを持ちます。

  1. 機能の整合性:

    • ListenUnixgramは、その名前が示す通り、Unixドメインデータグラムソケットをリッスンするための関数です。Unixドメインソケットは、IPネットワークのUDPとは異なるアドレス体系(ファイルパス)と通信メカニズムを持っています。
    • 以前の*UDPConnを返す実装では、返されたコネクションオブジェクトがnet.UDPConnのメソッド(例えば、IPアドレスやポート番号を扱うもの)しか提供せず、Unixドメインソケット固有の機能(例えば、ReadFromUnixWriteToUnixでUnixドメインアドレスを直接扱うこと)を利用できませんでした。これは、Unixドメインデータグラムソケットの本来の目的と機能に合致していませんでした。
    • *UnixConnを返すように変更することで、返されるコネクションオブジェクトはnet.UnixConnのすべてのメソッドを利用できるようになります。これにより、Unixドメインデータグラムソケットの特性を完全に活用し、送信元アドレスの取得や特定の宛先への送信が可能になります。
  2. APIの正確性:

    • Go 1のAPI互換性を破る変更であると明記されていますが、コミットメッセージにあるように「previous ListenUnixgram doesn't work in any use cases」であったため、実質的な影響は限定的であると判断されました。機能しないAPIを修正することは、長期的なAPIの健全性にとって重要です。
    • この変更により、ListenUnixgramのAPIは、その機能と戻り値の型が一致し、より直感的で正確なものとなりました。
  3. 内部実装の調整:

    • 戻り値の型を変更するだけでなく、内部的なソケットの作成と管理もUnixConnのセマンティクスに合わせる必要があります。
    • src/pkg/net/unixsock_posix.go内のListenUnixgramの実装では、最終的にnewUnixConn(fd)を呼び出して*UnixConnを返すように変更されています。これは、ソケットディスクリプタ(fd)がUnixドメインソケットとして適切に初期化され、UnixConnの構造体でラップされることを意味します。
    • テストコード(src/pkg/net/protoconn_test.go)も、ListenUnixgram*UnixConnを返すことを前提としたテストケース(WriteToUnixReadFromUnixの使用)が追加され、変更の正当性を検証しています。
  4. ドキュメントの更新:

    • doc/go1.1.htmlに、ListenUnixgramUnixConnを返すようになったこと、そしてReadFromWriteToメソッドがUnixConn上で利用可能になったことが明記されています。これは、APIの変更をユーザーに明確に伝えるために不可欠です。

この変更は、Go言語のnetパッケージが提供するUnixドメインソケットの機能が、より堅牢で使いやすいものになるための重要なステップでした。

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

このコミットにおける主要なコード変更は、src/pkg/net/unixsock_posix.gosrc/pkg/net/dial.go、そしてドキュメントファイルdoc/go1.1.htmlに集中しています。

  1. src/pkg/net/unixsock_posix.go:

    • ListenUnixgram関数のシグネチャが変更されました。
      --- a/src/pkg/net/unixsock_posix.go
      +++ b/src/pkg/net/unixsock_posix.go
      @@ -347,5 +348,5 @@ func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error) {
       	if err != nil {
       		return nil, err
       	}
      -	return newUDPConn(fd), nil
      +	return newUnixConn(fd), nil
       }
      
    • ListenUnixgramのコメントも更新され、戻り値が*UnixConnであることが明記されました。
      --- a/src/pkg/net/unixsock_posix.go
      +++ b/src/pkg/net/unixsock_posix.go
      @@ -328,16 +329,16 @@ func (l *UnixListener) SetDeadline(t time.Time) (err error) {
       	return setDeadline(l.fd, t)
       }
       
      -// ListenUnixgram listens for incoming Unix datagram 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.  The network net must be "unixgram".
      -func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error) {
      +// ListenUnixgram listens for incoming Unix datagram packets addressed
      +// to the local address laddr.  The returned connection c's ReadFrom
      +// and WriteTo methods can be used to receive and send packets with
      +// per-packet addressing.  The network net must be "unixgram".
      +func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
       	switch net {
       	case "unixgram":
       	default:
       		return nil, UnknownNetworkError(net)
       	}
      
  2. src/pkg/net/dial.go:

    • ListenPacket関数内で、"unixgram"ネットワークの場合にDialUnixの代わりにListenUnixgramを呼び出すように変更されました。
      --- a/src/pkg/net/dial.go
      +++ b/src/pkg/net/dial.go
      @@ -238,7 +238,7 @@ func ListenPacket(net, laddr string) (PacketConn, error) {
       		if a != nil {
       			la = a.(*UnixAddr)
       		}
      -		return DialUnix(net, la, nil)
      +		return ListenUnixgram(net, la)
       	}
       	return nil, UnknownNetworkError(net)
       }
      
  3. doc/go1.1.html:

    • Go 1.1のドキュメントに、ListenUnixgramUDPConnではなくUnixConnを返すようになったこと、そしてUnixConn上でReadFromおよびWriteToメソッドが利用可能になったことが追記されました。
      --- a/doc/go1.1.html
      +++ b/doc/go1.1.html
      @@ -84,6 +84,13 @@ The same is true of the other protocol-specific resolvers <code>ResolveIPAddr</c
       <code>ResolveUnixAddr</code>.
       </p>
       
      +<p>
      +The previous <code>ListenUnixgram</code> returned <code>UDPConn</code> as
      +arepresentation of the connection endpoint. The Go 1.1 implementation
      +returns <code>UnixConn</code> to allow reading and writing
      +with <code>ReadFrom</code> and <code>WriteTo</code> methods on
      +the <code>UnixConn</code>.
      +</p>
       
       <h3 id="time">time</h3>
       <p>
      
  4. src/pkg/net/protoconn_test.go:

    • TestUnixConnSpecificMethodsテストケースが拡張され、ListenUnixgramが返すUnixConnに対してWriteToUnixReadFromUnixが正しく機能することを確認するテストが追加されました。
    • 一時ファイルパスとしてp3が追加され、新しいListenUnixgramのテストに使用されています。

コアとなるコードの解説

  1. src/pkg/net/unixsock_posix.goにおけるListenUnixgramの変更:

    • シグネチャの変更: 最も重要な変更は、ListenUnixgram関数の戻り値の型が*UDPConnから*UnixConnに変更されたことです。
      • 変更前: func ListenUnixgram(net string, laddr *UnixAddr) (*UDPConn, error)
      • 変更後: func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error)
    • インスタンス生成の変更: 関数内部で、ソケットディスクリプタfdからコネクションオブジェクトを生成する際に、newUDPConn(fd)の代わりにnewUnixConn(fd)が呼び出されるようになりました。
      • newUDPConnはUDPソケットに特化したUDPConn型を生成しますが、newUnixConnはUnixドメインソケットに特化したUnixConn型を生成します。この変更により、ListenUnixgramが返すオブジェクトは、Unixドメインソケットの特性(例えば、ファイルパスを介したアドレス指定や、ReadFromUnix/WriteToUnixのようなUnixドメインソケット固有のメソッド)を正しく扱うことができるようになります。
  2. src/pkg/net/dial.goにおけるListenPacketの変更:

    • ListenPacket関数は、指定されたネットワークとローカルアドレスに基づいてパケットコネクションをリッスンするための汎用関数です。
    • 以前は、"unixgram"ネットワークの場合にDialUnixを呼び出していました。しかし、DialUnixは通常、クライアント側から特定のUnixドメインソケットに接続するために使用されるものであり、データグラムソケットをリッスンするListenUnixgramとは目的が異なります。
    • この変更により、"unixgram"ネットワークの場合は、正しくListenUnixgramが呼び出されるようになりました。これにより、ListenPacketを通じてUnixドメインデータグラムソケットをリッスンする際にも、新しいListenUnixgramの正しい動作が反映されるようになります。
  3. doc/go1.1.htmlにおけるドキュメントの更新:

    • Go 1.1のリリースノートに、このAPI変更が明記されました。これにより、Go 1.1にアップグレードする開発者は、ListenUnixgramの戻り値の型が変更されたこと、そしてUnixConn上でReadFromWriteToといったメソッドが利用可能になったことを認識できます。これは、APIの互換性を破る変更であるため、ユーザーへの明確な情報提供が非常に重要です。

これらの変更は、Go言語のnetパッケージにおけるUnixドメインデータグラムソケットのサポートを修正し、より堅牢で機能的なものにするためのものです。

関連リンク

参考にした情報源リンク

  • Go言語のnetパッケージ公式ドキュメント: https://pkg.go.dev/net
  • Unixドメインソケットに関する一般的な情報源 (例: Wikipedia, Linux man pagesなど)
  • Go 1.1 Release Notes (該当箇所): https://go.dev/doc/go1.1 (このコミットで更新されたdoc/go1.1.htmlの内容が反映されています)
  • Go言語のnetパッケージのソースコード (特にsrc/pkg/net/unixsock_posix.go, src/pkg/net/dial.go, src/pkg/net/protoconn_test.go)