1. ホーム
  2. スクリプト・コラム
  3. ゴラン

Go言語 初心者のための7つのチュートリアル VI ネットワーク・プログラミング

2022-02-07 08:44:10

1. ソケットプログラミング

Goでネットワークプログラムを書く場合、従来のようなコーディングの形式は見られません。以前は、ソケットを使ったプログラミングをする場合、以下のような手順で行っていました。

ソケットを作成する。 socket() 関数を使用します。

ソケットをバインドする bind() 関数を使用します。

リスニング:使用する listen() 関数を使用します。または、接続する場合は connect() 関数を使用します。

コネクションを受け付ける accept() 関数を使用します。

受信する。を使用します。 receive() 関数を使用します。または、送信: を使用します。 send() 関数を使用します。
Go言語標準ライブラリは、この手続きを抽象化し、カプセル化しています。どのようなプロトコルを使ってどのような形式の接続を確立するかにかかわらず、必要なのは net.Dial() を実行すればOKです。

1.1 Dial() 関数

Dial()関数のプロトタイプは以下のとおりである。

func Dial(net, addr string) (Conn, error)


ここで net パラメータはネットワークプロトコルの名前です。 addr パラメータは IP アドレスまたはドメイン名で始まり、ポート番号は : の後に、アドレスまたはドメイン名が続き、ポート番号は任意である。接続に成功した場合は接続オブジェクトが返され、そうでない場合は error .
一般的なプロトコルの呼び出しをいくつか見てみましょう。

TCP リンクです。

conn, err := net.Dial("tcp", "192.168.1.8:3000")


UDP リンク

conn, err := net.Dial("udp", "192.168.1.12:975")


ICMP リンク(プロトコル名使用)。

conn, err := net.Dial("ip4:icmp", "www.baidu.com")


ICMP リンク(プロトコル番号使用)。

conn, err := net.Dial("ip4:1", "10.0.0.3")


接続が正常に確立されたら、データの送受信を行うことができます。データを送信するには conn Write() を使用してデータを受け取るメンバーメソッドです。 Read() メソッドで受信します。

2. HTTP プログラミング

2.1 HTTPクライアント

Goの組み込み net/http パッケージは、最も簡潔な HTTP クライアントを実装しているので、サードパーティのネットワーク通信ライブラリ (例えば libcurl を使用することで、最もよく使われる HTTP GET POST メソッドを使用してデータを要求します。

基本的なメソッド

net/http パッケージ Client 型は、いくつかのメソッドを提供し、それを使って HTTP のリクエストに対応します。

func (c *Client) Get(url string) (r *Response, err error)
func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error)
func (c *Client) PostForm(url string, data url.Values) (r *Response, err error)
func (c *Client) Head(url string) (r *Response, err error)
func (c *Client) Do(req *Request) (resp *Response, err error)


その方法の概要は以下のとおりです。

  • http.Get()

リソースを要求するには、以下のサンプルコードでhttp.Get()メソッド(http.DefaultClient.Get()と同等)を呼び出すだけです。

resp, err := http.Get("http://example.com/")
if err ! = nil { // Handle the error ...
	return
}
defer resp.Body.close()
io.Copy(os.Stdout, resp.Body)


上記のコードは、ウェブサイトのホームページを要求し、そのページ内容を標準出力ストリームにプリントしています。

  • http.Post()

で始めるには POST を呼び出すだけです。 http.Post() メソッドに次の3つのパラメータを順番に渡してください。

要求された送信先URLは、POSTデータのビットストリーム([]byte形式)のリソースタイプ(MIMEType)になります。

次のサンプルコードは、画像をアップロードする方法を示しています。

resp, err := http.Post("http://example.com/upload", "image/jpeg", &imageDataBuf)
if err ! = nil{ // Handle the error
	return
}
if resp.StatusCode ! = http.StatusOK {// Handle the error
	return
}


  • http.PostForm()

http.PostForm() メソッドは、標準的なエンコーディング形式を application/x-www-form-urlencoded は、フォーム送信用です。次のサンプルコードは、新しい記事のためのHTMLフォーム送信をシミュレートしたものです。

resp, err := http.PostForm("http://example.com/posts", url.Values{"title": 
{"article title"}, "content": {"article body"}})
if err ! = nil{ // Handle the error
	return
}


  • http.Head()

HTTPのHeadリクエストメソッドは、ターゲットURLのヘッダー情報であるHTTPヘッダーを返さずに、ヘッダーのみを要求することを示します。
Goの組み込みの net/http パッケージも提供します。 http.Head() メソッドと同じです。 http.Get() メソッドと同じです。
パラメータとしてターゲットURLを渡すだけです。次のコード例では、ウェブサイトのトップページのHTTPヘッダー情報を要求します。

resp, err := http.Head("http://baidu.com/")


  • (*http.Client).Do()

ほとんどの場合 http.Get() http.PostForm() を起動すれば十分なのですが、もし
HTTPリクエストはよりカスタマイズされた情報を必要とするため、以下のようなカスタムHttpヘッダーフィールドを設定したい。

  • User-Agent" をカスタムで設定します。
  • クッキーの受け渡し

この時点では net/http パッケージ http.Client オブジェクトを作成します。 Do() メソッドを実装しています。

req, err := http.NewRequest("GET", "http://baidu.com", nil) 
// ...
req.Header.Add("User-Agent", "Gobook Custom User-Agent") 
// ...
client := &http.Client{ // ... } 
resp, err := client.Do(req)


2.2 HTTPサーバーサイド

2.2.1 HTTPリクエストの処理

を使用することで net/http パッケージによって提供されます。 http.ListenAndServe() メソッドは、指定されたアドレスでリッスンし、HTTPをオープンします。このメソッドのサーバー側のプロトタイプは次のとおりです。

func ListenAndServe(addr string, handler Handler) error


このメソッドは、指定された TCP ネットワークアドレス addr をリッスンし、サーバー側のハンドラを呼び出して着信した接続要求を処理します。このメソッドには2つのパラメータがあります:最初のパラメータ addr 2番目のパラメータはサーバー側のハンドラで、通常は空です。つまり、サーバー側で http.DefaultServeMux を処理し、サーバーサイドに書かれたビジネスロジック・ハンドラは http.Handle() または http.HandleFunc() デフォルトのインジェクション http.DefaultServeMux を以下のコードに追加します。

http.Handle("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(":8080", nil))


net/http パッケージはまた http.ListenAndServeTLS() メソッドを使用します。 HTTPS 接続要求。

func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error


ListenAndServeTLS() ListenAndServe() は同じ動作をしますが、違いは HTTPS を要求します。さらに、証明書と一致する秘密鍵を含む関連ファイルがサーバー上に存在する必要があり、例えば、以下のようになります。 certFile に対応する SSL certificate ファイルパスの場合は keyFile 対応する証明書の秘密鍵ファイルへのパスです。証明書が認証局によって署名されている場合は certFile パラメータには、サーバに保存されているパスを CA 認証済み SSL Certificate .

3. RPC プログラミング

Goでは、標準ライブラリで提供されるnet/rpcパッケージがRPCプロトコルに必要な関連詳細を実装しており、開発者はこのパッケージを利用してRPC用のサーバサイドおよびクライアントサイドプログラムを簡単に書くことができ、Goで開発した複数のプロセス間で非常に簡単に通信を行うことができるようになっています。

net/rpc このパッケージでは RPC クライアントアプリケーションは、ネットワークやその他のI/O接続を介して、リモートオブジェクトのパブリックメソッド(大文字で始まり、外部から呼び出し可能である必要があります)を呼び出すことができます。RPCサーバー上では、オブジェクトをアクセス可能なサービスとして登録し、オブジェクトのパブリックメソッドをリモートでアクセスできるようにすることができます。RPCサーバーは、異なるタイプのオブジェクトを複数登録することができますが、同じタイプのオブジェクトを複数登録することはできません。

これらの条件を満たすオブジェクトのメソッドのみが、RPCサーバーによってリモート・アクセスが可能になるように設定されます。

  • オブジェクトの外部で公に呼び出すことができるメソッドでなければならない(初期値は大文字)。
  • は 2 つの引数を持ち、その両方がパッケージの外側でアクセス可能な型であるか、Go ビルトインでサポートされている型でなければなりません。
  • 第2引数はポインタでなければならない。
  • このメソッドは error 型の値を返す必要があります。

以上の4つの条件を簡単に表すと、次のようなコード行になります。

func (t *T) MethodName(argType T1, replyType *T2) error


上記のコードでは、型 T、T1、T2 はデフォルトで Go の組み込みの encoding/gob パッケージでエンコードとデコードを行います。

メソッドの第一引数(MethodName)は、gobのエンコードとデコードを示す。 RPC に返すパラメータを示し、第2パラメータはクライアントから渡された RPC クライアントの場合、このメソッドは最終的に error 型の値です。
RPC サーバーは rpc.ServeConn を使用して、単一の接続要求を処理します。ほとんどの場合、リクエストは TCP または HTTP このサービスを作成するためにネットワークアドレスでリスニングすることは、良い選択肢です。

3.1 Go における RPC のサポートと処理

Go では、標準ライブラリが net/rpc パッケージは RPC このプロトコルを使って、開発者は簡単に RPC 用のサーバーサイドとクライアントサイドのプログラムを書くことができ、Go で開発された複数のプロセス間の通信を非常に簡単に行うことができるのです。

net/rpc このパッケージでは RPC クライアントアプリケーションは、ネットワークやその他のI/O接続を介してリモートオブジェクトのパブリックメソッド(大文字で始まり、外部から呼び出し可能でなければなりません)を呼び出すことができます。その際 RPC サーバー側では、オブジェクトをアクセス可能なサービスとして登録し、そのオブジェクトのパブリックメソッドをリモートでアクセスできるようにすることができます。A RPC サーバーサイドでは、異なるタイプのオブジェクトを複数登録することは可能ですが、同じタイプのオブジェクトを複数登録することはできません。

以下の条件を満たすオブジェクトのメソッドのみを RPC サーバーにリモートアクセスできるように設定されている。

  • オブジェクトの外部で公に呼び出し可能なメソッドである必要があります(初期値は大文字)。
  • は2つの引数を持ち、両引数はパッケージの外部からアクセス可能な型でなければなりません。 Go 内部でサポートされている型。
  • 第2引数はポインタでなければならない。
  • メソッドは error 型の値を返さなければなりません。

以上の4つの条件を簡単に表現すると、次のような行になります。

func (t *T) MethodName(argType T1, replyType *T2) error


上記のコードでは、型 T、T1、T2 はデフォルトで Go の組み込みの encoding/gob パッケージでエンコードとデコードを行います。に関しては encoding/gob パッケージで、後述する。

このメソッドの最初のパラメータ(MethodName)は、RPCクライアントから渡されるパラメータを示し、2番目のパラメータは、RPCクライアントに返されるパラメータを示します。 RPC を指定し、最後にエラータイプの値を返します。

RPC サーバー側では rpc.ServeConn を使用して、単一の接続要求を処理します。ほとんどの場合、リクエストは TCP または HTTP このサービスを作成するためにネットワークアドレスでリスニングすることは、良い選択肢です。

3.2 Gobの紹介

Gob のシリアル化されたデータ構造をエンコードおよびデコードするための Go ツールです。 Go は標準ライブラリに組み込まれています。 encoding/gob パッケージで使用することができます。を使用したデータ構造です。 Gob は、シリアライズ後のネットワーク転送に使用することができます。

とは JSON または XML このテキストベースの記述データ交換言語は Gob はバイナリ符号化されたデータストリームであり Gob ストリームは自明であり、高い効率を確保しつつ、十分な表現力を有している。

への対応として Go をデータ構造のエンコードとデコードのための専用のシリアライゼーションメソッドとして使用することを意味します。 Gob は言語を超えて使用することはできない。また Go net/rpc パッケージの場合、データを伝送するために必要なコーデックは、デフォルトでは Gob . このため Gob のみを使用するように制限されています。 Go 言語しか使えないということです。 Go RPC はプロセス間通信を実装している。

しかし、たいていの場合、私たちは Go で書かれた RPC サーバー(またはクライアント)は、Python、Java、または他のプログラミング言語で実装されているかどうかにかかわらず、おそらく汎用的で言語に依存しないことを好むでしょう RPC は、クライアントと通信することができます。

3.3 エレガントなRPCインターフェースの設計

Go's net/rpc は、データ転送の前後にコーデックのインターフェース定義を実装しているため、柔軟性があります。つまり、開発者はデータの転送方法や、RPCサーバとクライアントがどのように相互作用するかをカスタマイズすることができるのです。
RPC 以下のコーデックインタフェースが提供されています。

type ClientCodec interface {
	WriteRequest(*Request, interface{}) error 
	ReadResponseHeader(*Response) error
	ReadResponseBody(interface{}) error
	Close() error
}

type ServerCodec interface {
	ReadRequestHeader(*Request) error 
	ReadRequestBody(interface{}) error 
	WriteResponse(*Response, interface{}) error
	Close() error
}


インターフェース ClientCodec が定義しています。 RPC クライアントがどのようにして RPC セッションがリクエストを送信し、レスポンスを読み取る。クライアントプログラムはリクエストを送信し、レスポンスを読み取るのに WriteRequest() メソッドを使ってRPCコネクションにリクエストを書き込むことができます。 ReadResponseHeader() ReadResponseBody() を使用して、サーバー側からの応答メッセージを読み取ります。全体の処理が実行されると、そのレスポンスは Close() メソッドを使用して接続を閉じます。

インターフェース ServerCodec が定義している RPC サーバー側がどのように新しいRPCを RPC セッションはリクエストを受信し、レスポンスを送信します。サーバー側のプログラムは、リクエストを ReadRequestHeader() ReadRequestBody() メソッドは、RPC 接続から要求を読み取り、WriteResponse() メソッドを介してその接続内の RPC クライアントに応答を送信します。処理が完了すると、そのレスポンスは Close() メソッドで接続を閉じます。

上記のインターフェイスを実装することで、送信前後のデータのエンコードやデコードの方法を、単に Gob . 同様に、"Subject "セクションをカスタマイズすることも可能です。 RPC は、サーバーサイドとクライアントサイドのインタラクションの挙動を示します。事実上 Go 標準ライブラリは net/rpc/json を実装するパッケージの集合です。 rpc.ClientCodec rpc.ServerCodec のインターフェースは JSON-RPC モジュールになります。

以上、Go言語6ネットワークプログラミング入門7チュートリアルNo.の詳細です。Go言語ネットワークプログラミングの詳細については、Scripting Houseの他の関連記事にもご注目ください

Goの学習方法

初めてGoを使う人は、こんな風に勉強するといいですよ〜。

Goを始めるための7つの記事

最初の記事 Goの紹介

第2部 プログラム構造&&データ型の紹介

第3部 関数-メソッドインタフェースの紹介

第4部 チャネルとGoroutineの並行プログラミング

第五部 ファイルやパッケージの操作・取り扱い

タイトルVII GCガベージコレクション 3色マーカー