GoでTCP サーバ/クライアントを動かしてみた
Goを使って、TCP通信でサーバー⇄クライアント間でTCP通信を行なっていきたいと思います。
Goにには、標準でnet
パッケージというものが用意されているので今回はこちらを使用します。
TCPとは
TCPとは、信頼性の高い通信を実現するために使用されるプロトコルになります。IPと同様にインターネットにおいて標準的に利用されています。TCPは、IPの上位プロトコルでトランスポート層で動作するプロトコルで、ネットワーク層のIPとセッション層以上のプロトコルの橋渡しをする形で動作しています。
TCPソケット
TCP/IPアプリケーションを作成するための抽象化されたインターフェースのことです。 互いのソケットをネットワークを通して接続し、通信をすることが可能となります。
サーバー側の実装
package main import ( "io" "log" "net" "time" ) func receiveTCPConn(ln *net.TCPListener) { for { err := ln.SetDeadline(time.Now().Add(time.Second * 10)) if err != nil { log.Fatal(err) } conn, err := ln.AcceptTCP() if err != nil { log.Fatal(err) } go echoHandler(conn) } } func echoHandler(conn *net.TCPConn) { defer conn.Close() for { _, err := io.WriteString(conn, "Socket Connection!!\n") if err != nil { return } time.Sleep(time.Second) } } func main() { tcpAddr, err := net.ResolveTCPAddr("tcp", ":8080") if err != nil { log.Fatal(err) } ln, err := net.ListenTCP("tcp", tcpAddr) if err != nil { log.Fatal(err) } receiveTCPConn(ln) }
net.ResolveTCPAddr()
メソッドを使用し、ソケットの作成とアドレスとポートのバインドを行いますnet.ListenTCP()
メソッドで、リッスン。
AcceptTCP()
メソッドで、クライアントからの接続を待ち受けます。
作成したechoHandler
に接続情報を渡します。リクエストを受けたら、Socket Connection!!
を返しますようにしてます。ゴルーチンを使用してるのは、1つのリクエストの処理が完了するまでブロックされるので、別スレッドで実行し複数リクエストに対応するためです。
クライアント側の実装
クライアント側の実装を行なっていきます。
package main import ( "io" "log" "net" "os" ) func response(dst io.Writer, src io.Reader) { if _, err := io.Copy(dst, src); err != nil { log.Fatal(err) } } func main() { conn, err := net.Dial("tcp", ":8080") if err != nil { log.Fatal(err) } response(os.Stdout, conn) }
net.Dial()
メソッドを使用し、localhost:8080
に接続します。
response
メソッドで、標準出力に、conn
をコピーして出力します。
$ go run server/server.go
$ go run client/client.go Socket Connection!! Socket Connection!! Socket Connection!! Socket Connection!!
通信できてますね。
ネットワークわからないって方は、まずはマスタリングTCP /IP入門編
を読んでみてはいかがでしょうか。
かなりわかりやすく解説されているので、最初に勉強するにはうってつけかと思います。