golangでTCPを使ってみた

環境情報

go version : 1.8

os : kubuntu 16

やったこと

  1. LookupPort
  2. TCP Client

LookupPort

現在、実行してるサービスのポートを調べることができます。

net.LookupPort(network, service string) (int, error)

networkは"tcp"か"udp"になります

serviceは実行しているサービス、例えば"telent"、"http"、"ssh"とか

exsample

func main() {
    port, err := net.LookupPort("tcp", "http")
    if err != nil {
        fmt.Println("Error : ", err.Error())
        os.Exit(2)
    }
    fmt.Println("Service port : ", port)
}

TCP Client

いよいよTCPの話です。

まずはTCP関連でよく使う構造体から

type TCPAddr struct {
    IP   IP
    Port int
    Zone string
}

IPとPortとZoneを内包しています。 ZoneはIPv6で使用するZoneになります。IPとPortはそのままの意味かな。

この構造体を作るためには下記のメソッドを使います

net.ResolveTCPAddr(net, addr string) (*TCPAddr, err)

netにはネットワークタイプを(tcp, tcp4, tcp6)、addrにはアドレスとポートを入れます。 addrのフォーマットは「IPアドレスorホスト名:ポート」になります 例:www.google.com:80

次にTCPAddr構造体を使って実際にサーバとつなぎ合わせます

net.DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error)

netにはResolveTCPAddr同様でtcp、tcp4、tcp6のどれかを入れ、laddr、raddrにはTCPAddrを入れます。 それぞれladdrはローカル、raddrはリモートを表しています。 なので接続したいサーバのTCPAddrはraddrに入れます。(laddrには基本的にはnilが入ります)

ここで取得したTCPConnを使い実際のメッセージのやり取りを行います。 このTCPConnにたいして、write、readを行いリモートのサーバと通信を行います。

(c *TCPConn) Write(b []byte) (int, error)

bには送るメッセージを入れます(そのまんま)

最後にサーバからレスポンスを受け取り、読み込みます

ioutil.ReadAll(io.Reader) ([]byte, error)

io.Readerから読み込みます。これはサーバからレスポンスをすべて受け取るまでブロックして、すべて受け取ってから読み込みを開始します。

これで一通りTCPの通信の流れができます。 TCPクライアントのサンプルとしてHTTP通信をしたいと思います

exsample

func main() {
    tcpAddr, err := net.ResolveTCPAddr("tcp4", "www.google.com:80")
    if err != nil {
        fmt.Println("net resolve TCP Addr error ")
        os.Exit(1)
    }
    conn, err := net.DialTCP("tcp", nil, tcpAddr)
    if err != nil {
        fmt.Println("net dial tcp error ")
        os.Exit(1)
    }
    _, err = conn.Write([]byte{"HEAD / HTTP/1.0 \r\n\r\n)
    if err != nil {
        fmt.Println("conn write error ")
        os.Exit(1)
    }
    result, err := ioutil.ReadAll(conn)
    if err != nil {
        fmt.Println("ioutil read all error ")
        os.Exit(1)
    }
    fmt.Println(string(result))
}

これでTCP通信ができるようになりました(やーー!!)