golang でtelnetサーバーとクライアントを用意してみました。
github.com/reiver/go-telnet というライブラリがあるので、
こちらを使えば好きなtelnetサーバーを簡単に用意できるみたいです。
telnetとは
telnetは、リモートサーバーを操作する為のコマンドでしたが、
平文をそのまま送信する為に盗聴される危険性があるため、暗号化通信が出来るsshに取って代わられたものです。
なので、サーバー操作を目的として、telnetサーバーをわざわざ外部に公開しているところはないでしょう。
今では、そういったコマンドなどのソフトフェアとしての意味よりも、
アプリケーション層プロトコルとして
単純に平文での通信プロトコル自体をtelnetと呼ぶ事の方が多いようです。
用途としては、ローカルマシン内での通信テストや
安全なLAN内でのみ通信する場合に使えるのかなと。
go-telnet
Go言語で実装されたTelnetプロトコルの実装ライブラリ
https://github.com/reiver/go-telnet
go get -v -u github.com/reiver/go-telnet
サンプルに記載のサーバーソースと、クライアントソースを使えば、簡単にエコーしてくれるものが出来上がります。
また、SSL認証をおこなう。TELNETSもサポートしているようです。
Serverサンプル
go-telnetを使った、サーバー側のサンプルです。
ServeTELNETメソッドをもった構造体をHandlerとして、
telnet.ListenAndServeメソッドに渡せば良いだけです。
telnet接続されると、ServeTELNETメソッド内で、Readerから読み取り待機し続けます。
接続が切れると、errを返す為、ループから抜けるようになってます。
func server() error {
return telnet.ListenAndServe(fmt.Sprintf(":%d", 5555), handler{})
}
type handler struct{}
func (h handler) ServeTELNET(ctx telnet.Context, w telnet.Writer, r telnet.Reader) {
println("-- connect --")
var buffer [1]byte
p := buffer[:]
for {
n, err := r.Read(p)
if n > 0 {
bytes := p[:n]
print(string(bytes))
}
if nil != err {
break
}
}
println("-- disconnect --")
}
Clientサンプル
クライアント側のサンプルです。
こちらも似たようなもので、CallTELNETメソッドを実装した構造体をCallerとして
telnet.DialToAndCallメソッドに渡すだけです。
指定の接続先に接続が成功すると、CallTELNETメソッドがコールされます。
Writerに対して、バイト配列を送信する事ができます。
Readerから、サーバーから来たデータを読み取る事ができます。
今回は、標準入力を一方的に送信するようなサンプルです。
func client() error {
return telnet.DialToAndCall("localhost:5555", caller{})
}
type caller struct{}
func (c caller) CallTELNET(ctx telnet.Context, w telnet.Writer, r telnet.Reader) {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
oi.LongWrite(w, scanner.Bytes())
oi.LongWrite(w, []byte("\n"))
}
}
起動デモ
サーバーを立ち上げてみて、クライアントで接続してみるデモです。
もちろん、telnetコマンドでも接続して、メッセージを送ることが出来ます。
simple-telnetコマンド
あと、上記のサンプルを元に、telnetでサーバーとクライアントを用意するコマンドを作成しました。
https://gitlab.com/tyabuta/go-simple-telnet
shellscriptで 、telnet接続してメッセージ送るだけの時に、代わりに使えるかと思います。
echo "送りたいメッセージ" | simple-telnet -H localhost -P 5555
おしまい
telnetについて、多少イメージできるようになりました。
コマンドとしてのtelnetと、プロトコルとしてのtelnet。
どちらの話をしているのか、認識が違うと会話できないなと思いました。