いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

ncコマンド無しでUDP通信の確認をする (bash)

概要

知らなかったので、忘れないうちにメモメモ。

先日、ncコマンドを使った通信確認について記載しました。

devlights.hatenablog.com

最近、以下の記事を知りました。

bash には、以下のようにしてTCPやUDPの通信する仕組みがあるんですね。知らなかった。。。

/dev/{tcp,udp}/ホスト/ポート

ローカルホストでudpでポート 32222 の場合は以下のようになります。

/dev/udp/127.0.0.1/32222

bash の man ページの REDIRECTION の章に以下の記載がありました。

/dev/tcp/host/port

If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open the corresponding TCP socket.

/dev/udp/host/port

If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open the corresponding UDP socket.

使う場合は、新しいファイルディスクリプタ (FD) を作ってやり取りします。0, 1, 2 は予約済みなので、通常は3ですね。

ちなみに

  • 0
    • 標準入力(STDIN)
  • 1
    • 標準出力(STDOUT)
  • 2
    • 標準エラー出力(STDERR)

です。

新しいディスクリプタ作る場合は exec コマンドを使って

$ exec 3<>/dev/udp/127.0.0.1/32222

という風にします。

あとは、ここに書き込んだり、ここから読み込んだりできます。

$ exec 3<>/dev/udp/127.0.0.1/32222

# write
$ echo -e 'hello\n' >&3

# read
$ cat <&3

試してみる

試してみるために、受け取った文字列を大文字にして返すエコーサーバみたいなのを用意。

エラー処理とかは手抜きして無しです。言語は何でもいいのですが、今回はGoで作りました。

package main

import (
        "fmt"
        "net"
        "strings"
)

func main() {
        addr := &net.UDPAddr{
                IP:   net.ParseIP("127.0.0.1"),
                Port: 32222,
        }

        conn, _ := net.ListenUDP("udp", addr)
        for {
                buf := make([]byte, 1024)
                n, a, _ := conn.ReadFromUDP(buf)

                s := string(buf[:n])
                fmt.Println(s)

                conn.WriteToUDP([]byte(strings.ToUpper(s)), a)
        }
}

で、これを起動しておきます。

$ go run .

んで、別のターミナルで疎通確認をしてみます。

まずは、ファイルディスクリプタを作ります。今回はデータを送って、返答を受け取りたいので「読み書き両用」で開きます。

$ exec 3<>/dev/udp/127.0.0.1/32222 

3<> としている部分が「読み書き両用」の指定です。書き込み専用なら3>、読み込み専用なら 3< ですね。

データを送ってみます。

$ echo -e 'hello\n' >&3

そうすると、サーバ側のコンソールに hello って表示されます。

サーバ側は、その後データを返送しているので、読み取ってみます。

$ cat <&3
HELLO

ちゃんと返ってきました。あとはそのままだとずっと cat が標準入力を待っているので Ctrl-c して終わり。

このやり方知っていると、最悪 nc コマンドすら入っていない環境でもなんとかなりますね。

参考情報

golang.org

ascii.jp

unix.stackexchange.com


過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com