この記事は 東京理科大学 Advent Calendar 2018 6日目の記事です。
はじめに
今回Goのnetパッケージを使ってTCPソケット通信を扱う機会があったので、同じnetパッケージで扱うことのできるUDPソケット通信と比較してみました。
比較方法
クライアント側からサーバ側にhello
とたくさん送り、そのまま出力した時の両者の違いをみます。
TCPソケット通信
TCPによる通信ではデータをバイトストリームと呼ばれるbyte型のひと続きのデータとして扱います。
・クライアント
クライアントのコードは以下です。
package main
import (
"log"
"net"
)
func main() {
conn, err := net.Dial("tcp", "localhost:8088")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
// メッセージを送信する
for {
msg := "hello"
conn.Write([]byte(msg))
}
}
・サーバ
サーバのコードは以下です。
package main
import (
"fmt"
"log"
"net"
)
func main() {
listener, err := net.Listen("tcp", "localhost:8088")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
defer conn.Close()
go handleconn(conn)
}
}
func handleconn(conn net.Conn) {
buf := make([]byte, 1024) // 1024バイトのスライスを用意
// 送られてきたメッセージを出力
for {
n, _ := conn.Read(buf)
fmt.Println(string(buf[:n]))
}
}
実行結果
$ go run tcp_server.go
hellohellohellohellohellohellohellohellohello
hellohellohellohellohellohello
hello
hellohellohellohello
hellohello
hello
hello
hello
...
UDPソケット通信
UDPによる通信ではデータを独立したパケットのデータグラムとして扱います。
・クライアント
クライアントのコードは以下です。
package main
import (
"log"
"net"
)
func main() {
conn, err := net.Dial("udp", "localhost:8088")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
// メッセージを送信する
for {
msg := "hello"
conn.Write([]byte(msg))
}
}
・サーバ
サーバのコードは以下です。
package main
import (
"fmt"
"log"
"net"
)
func main() {
udpAddr, err := net.ResolveUDPAddr("udp", ":8088")
if err != nil {
log.Fatal(err)
}
conn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
log.Fatal(err)
}
for {
defer conn.Close()
go handleconn(conn)
}
}
func handleconn(conn *net.UDPConn) {
buf := make([]byte, 1024) // 1024バイトのスライス
// 送られてきたメッセージを出力
for {
n, _ := conn.Read(buf)
fmt.Println(string(buf[:n]))
}
}
実行結果
$ go run udp_server.go
hello
hello
hello
hello
hello
hello
hello
hello
...
まとめ
以上の結果から、TCPではデータをストリームとして扱っているので何も処理をせずにそのまま出力した場合はhello
という文字列が連結されて出力される場合があることがわかった。
また、UDPではデータをパケットごとにデータグラムとして扱っているためそのまま出力してもhello
という文字列が区切られて出力されることがわかった。
蛇足
UDPと同じ出力結果になるようにTCPで処理をしようとした場合、
データの末尾に\nなどの区切り文字を用意する
データのヘッダにデータのバイト数をつけて送信する
ことで処理ができます。