TCP scanner【Go】
bufio packageのScannerを使って1行ずつ読み込むことができます。
TCP接続した情報を読み込む例を示します。
main.goです。
func main() { li, err := net.Listen("tcp", ":8080") if err != nil { log.Fatal(err) } for { conn, err := li.Accept() if err != nil { log.Fatal(err) } go handle(conn) } } func handle(conn net.Conn) { scanner := bufio.NewScanner(conn) for scanner.Scan() { fmt.Println(scanner.Text()) } if err := scanner.Err(); err != nil { log.Fatal(err) } defer conn.Close() }
上記を実行し、ブラウザ上で:8080にアクセスすると、接続情報が出力されます。
別のターミナルからtelnetを使ってlocalhost 8080に接続すると、
そのターミナルに入力した値が、そのままファイル実行側のターミナルに出力されます。
また、forループの中で、Fprintを使用すると書き込みも行うことができます。
for scanner.Scan() { fmt.Println(scanner.Text()) fmt.Fprintf(conn, "You said, %v", scanner.Text()) }
bufio.NewScannerでポインタを作成した後に、Splitメソッドを使うと、
行の区切り方を指定することもできます。
scanner := bufio.NewScanner(conn) scanner.Split(bufio.ScanWords) // 単語で区切る
bufio.Scannerは、ReadString()やReadBytes()よりも記述量が少なくなり、便利ではありますが、1行のデータ量が、上限を超えてしまうとscanを中断してしまう、という問題があります。デフォルトですと、その上限は65536バイトです。
あらかじめ1行のサイズ上限がわかっている場合には、scanner.Buffer()を使って最大のバッファサイズを指定します。
const ( initialBufSize = 10000 maxBufSize = 1000000 ) func handle(conn net.Conn) { scanner := bufio.NewScanner(conn) buf := make([]byte, initialBufSize) scanner.Buffer(buf, maxBufSize) ... }
scanが始まった後にscanner.Buffer()を実行するとpanicが発生します。
あらかじめ1行の上限がわからない場合は、bufio.Reader.ReadBytes()などを使用するのがよいでしょう。
参考