SCTPという、TCPとUDPのよいとこ取りをしたようなプロトコルがある。「
SCTP(ネットワーク通信)」に書いたとおり、echoサーバを作成したが、動作確認のためにクライアントが必要になった。
telnetなどのTCP用のツールは使えないので、クライアントのプログラムも作成したが、もっと簡単にためせるツールがないかと思っていたら、「
socat」というコマンドを見つけた。
netcat(nc)(「
netcat - ネットワーク万能ツール」を参照)をさらに機能強化して、これでもかというくらいいろいろオプションが指定できるようになっている。
あろうことかnetcatでは封印されているコマンドの実行も可能になっている。
socatインストール
Ubuntu10.10もFedora14もパッケージが用意されているので、aptやyumでインストール可能。
使用例
クライアント/サーバモデル
netcatに書いたのと同様、クライアントの標準入力の入力内容を、サーバ側の標準出力に出力するには以下のようにする。
■サーバ側
$ socat TCP4-LISTEN:8080 STDOUT <-- 8080で受け取った内容を標準出力へ
テストデータ <-- クライアントで入力した内容が出力される。
■クライアント側
$ socat STDIN TCP4:localhost:8080 <-- 標準入力をlocalhostの8080ポートへ出力
テストデータ <-- 入力内容
^C <-- Ctrl+Cで終了。コネクションが切れるので相手も終了する。
上記のサーバだと、コネクションがきれるとsocatは終了してしまい、終了するとlistenポートがTIME_WAITになって再起動してもしばらくは同じポート番号にbindできない。
そのため、以下のように「fork」と「reuseaddr」をつけることで、コネクションがきれても終了せず、ポートの再利用が可能なサーバが起動できる。
$ socat TCP4-LISTEN:8080,fork,reuseaddr STDOUT
なお、netcatは同時に1コネクションしかデータをやりとりできないが、socatは「fork」を指定することで、接続のたびにsocatが起動され、複数のコネクションを同時に扱うことができるようになる。
ファイル転送
ファイル転送は、上記の例で標準入力を転送元ファイル、標準出力を転送先ファイルとすればよい。
ファイルを指定するには、OPEN:<ファイル名>とする。デフォルトではファイルがないとエラーになるので、「create=<bool>」をつけている。
■サーバ側
$ ls outfile.txt <-- ファイルがないことを確認。
ls: outfile.txtにアクセスできません: そのようなファイルやディレクトリはありません
$ socat TCP4-LISTEN:8081,fork,reuseaddr OPEN:outfile.txt,creat=1 <-- 受信内容をoutfile.txtをオープンして受信
^C <-- 終了させる。(forkがなければ、クライアントの終了と共に終了する。)
$ cat outfile.txt
テストデータだよ。 <-- たしかに転送されている。
■クライアント側
$ cat infile.txt
テストデータだよ。 <-- 入力ファイルの内容
$ socat OPEN:infile.txt TCP4:localhost:8081 <-- inifile.txtをオープンして内容を送信
$
echoサーバ
以下のように出力を「SYSTEM:<コマンド>」とすると、コマンドを起動できる。(Hobbit版のnetcatの-eオプションと同じ)
以下のようにするとechoサーバが簡単に作れる。
■サーバ側
$ socat TCP4-LISTEN:8081 SYSTEM:cat <-- 受信内容がcatコマンドの入力となり、catの出力が送信元に出力される。
■クライアント側
$ socat STDIN TCP4:localhost:8081
echoされるよ <-- 入力内容
echoされるよ <-- サーバから出力された内容
サーバのcatの出力先のしくみいまいちよくわからないが、クライアントで入力を標準入力でなくファイルにすると、指定したファイルにcatの出力が追記された。
なので、クライアントの入力に対して出力される模様。
TCSPを使う。
もともと、TCSP用のクライアントがほしくて探したツールなので、SCTPでechoサーバとクライアントをやってみる。
■サーバ側
$ socat SCTP4-LISTEN:8081 SYSTEM:cat <-- 受信内容がcatコマンドの入力となり、catの出力が送信元に出力される。
■クライアント側
$ socat STDIN SCTP4-CONNECT:localhost:8081
echoされるよ <-- 入力内容
echoされるよ <-- サーバから出力された内容
これで、自分が作ったSCTPのechoサーバとも通信できた。
その他の例や、オプションの詳細はmanを見てください。以下のようにすると、使用可能なオプションが表示されます。
$ socat -h
socat by Gerhard Rieger - see www.dest-unreach.org
Usage:
socat [options] <bi-address> <bi-address>
options:
-V print version and feature information to stdout, and exit
-h|-? print a help text describing command line options and addresses
-hh like -h, plus a list of all common address option names
-hhh like -hh, plus a list of all available address option names
-d increase verbosity (use up to 4 times; 2 are recommended)
-D analyze file descriptors before loop
-ly[facility] log to syslog, using facility (default is daemon)
-lf<logfile> log to file
-ls log to stderr (default if no other log)
-lm[facility] mixed log mode (stderr during initialization, then syslog)
-lp<progname> set the program name used for logging
-lu use microseconds for logging timestamps
-lh add hostname to log messages
-v verbose data traffic, text
-x verbose data traffic, hexadecimal
-b<size_t> set data buffer size (8192)
-s sloppy (continue on error)
-t<timeout> wait seconds before closing second channel
-T<timeout> total inactivity timeout in seconds
-u unidirectional mode (left to right)
-U unidirectional mode (right to left)
-g do not check option groups
-L <lockfile> try to obtain lock, or fail
-W <lockfile> try to obtain lock, or wait
-4 prefer IPv4 if version is not explicitly specified
-6 prefer IPv6 if version is not explicitly specified
bi-address:
pipe[,<opts>] groups=FD,FIFO
<single-address>!!<single-address>
<single-address>
single-address:
<address-head>[,<opts>]
address-head:
abstract-client:<filename> groups=FD,SOCKET,RETRY,UNIX
abstract-connect:<filename> groups=FD,SOCKET,RETRY,UNIX
abstract-listen:<filename> groups=FD,SOCKET,LISTEN,CHILD,RETRY,UNIX
abstract-recv:<filename> groups=FD,SOCKET,RETRY,UNIX
abstract-recvfrom:<filename> groups=FD,SOCKET,CHILD,RETRY,UNIX
abstract-sendto:<filename> groups=FD,SOCKET,RETRY,UNIX
create:<filename> groups=FD,REG,NAMED
exec:<command-line> groups=FD,FIFO,SOCKET,EXEC,FORK,TERMIOS,PTY,PARENT,UNIX
fd:<num> groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
gopen:<filename> groups=FD,FIFO,CHR,BLK,REG,SOCKET,NAMED,OPEN,TERMIOS,UNIX
interface:<interface> groups=FD,SOCKET
ip-datagram:<host>:<protocol> groups=FD,SOCKET,RANGE,IP4,IP6
ip-recv:<protocol> groups=FD,SOCKET,RANGE,IP4,IP6
ip-recvfrom:<protocol> groups=FD,SOCKET,CHILD,RANGE,IP4,IP6
ip-sendto:<host>:<protocol> groups=FD,SOCKET,IP4,IP6
ip4-datagram:<host>:<protocol> groups=FD,SOCKET,RANGE,IP4
ip4-recv:<protocol> groups=FD,SOCKET,RANGE,IP4
ip4-recvfrom:<protocol> groups=FD,SOCKET,CHILD,RANGE,IP4
ip4-sendto:<host>:<protocol> groups=FD,SOCKET,IP4
ip6-datagram:<host>:<protocol> groups=FD,SOCKET,RANGE,IP6
ip6-recv:<protocol> groups=FD,SOCKET,RANGE,IP6
ip6-recvfrom:<protocol> groups=FD,SOCKET,CHILD,RANGE,IP6
ip6-sendto:<host>:<protocol> groups=FD,SOCKET,IP6
open:<filename> groups=FD,FIFO,CHR,BLK,REG,NAMED,OPEN,TERMIOS
openssl:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,OPENSSL
openssl-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,TCP,OPENSSL
pipe:<filename> groups=FD,FIFO,NAMED,OPEN
proxy:<proxy-server>:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,HTTP
pty groups=FD,NAMED,TERMIOS,PTY
readline groups=FD,READLINE,TERMIOS
sctp-connect:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,SCTP
sctp-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,SCTP
sctp4-connect:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,SCTP
sctp4-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,SCTP
sctp6-connect:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP6,SCTP
sctp6-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP6,SCTP
socket-connect:<domain>:<protocol>:<remote-address> groups=FD,SOCKET,CHILD,RETRY
socket-datagram:<domain>:<type>:<protocol>:<remote-address> groups=FD,SOCKET,RANGE
socket-listen:<domain>:<protocol>:<local-address> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE
socket-recv:<domain>:<type>:<protocol>:<local-address> groups=FD,SOCKET,RANGE
socket-recvfrom:<domain>:<type>:<protocol>:<local-address> groups=FD,SOCKET,CHILD,RANGE
socket-sendto:<domain>:<type>:<protocol>:<remote-address> groups=FD,SOCKET
socks4:<socks-server>:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,SOCKS4
socks4a:<socks-server>:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,SOCKS4
stderr groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
stdin groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
stdio groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
stdout groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
system:<shell-command> groups=FD,FIFO,SOCKET,EXEC,FORK,TERMIOS,PTY,PARENT,UNIX
tcp-connect:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP
tcp-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,TCP
tcp4-connect:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP4,TCP
tcp4-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,TCP
tcp6-connect:<host>:<port> groups=FD,SOCKET,CHILD,RETRY,IP6,TCP
tcp6-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP6,TCP
tun:<ip-addr>/<bits> groups=FD,CHR,NAMED,OPEN,INTERFACE
udp-connect:<host>:<port> groups=FD,SOCKET,IP4,IP6,UDP
udp-datagram:<host>:<port> groups=FD,SOCKET,RANGE,IP4,IP6,UDP
udp-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP4,IP6,UDP
udp-recv:<port> groups=FD,SOCKET,RANGE,IP4,IP6,UDP
udp-recvfrom:<port> groups=FD,SOCKET,CHILD,RANGE,IP4,IP6,UDP
udp-sendto:<host>:<port> groups=FD,SOCKET,IP4,IP6,UDP
udp4-connect:<host>:<port> groups=FD,SOCKET,IP4,UDP
udp4-datagram:<remote-address>:<port> groups=FD,SOCKET,RANGE,IP4,UDP
udp4-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP4,UDP
udp4-recv:<port> groups=FD,SOCKET,RANGE,IP4,UDP
udp4-recvfrom:<host>:<port> groups=FD,SOCKET,CHILD,RANGE,IP4,UDP
udp4-sendto:<host>:<port> groups=FD,SOCKET,IP4,UDP
udp6-connect:<host>:<port> groups=FD,SOCKET,IP6,UDP
udp6-datagram:<host>:<port> groups=FD,SOCKET,RANGE,IP6,UDP
udp6-listen:<port> groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP6,UDP
udp6-recv:<port> groups=FD,SOCKET,RANGE,IP6,UDP
udp6-recvfrom:<port> groups=FD,SOCKET,CHILD,RANGE,IP6,UDP
udp6-sendto:<host>:<port> groups=FD,SOCKET,IP6,UDP
unix-client:<filename> groups=FD,SOCKET,NAMED,RETRY,UNIX
unix-connect:<filename> groups=FD,SOCKET,NAMED,RETRY,UNIX
unix-listen:<filename> groups=FD,SOCKET,NAMED,LISTEN,CHILD,RETRY,UNIX
unix-recv:<filename> groups=FD,SOCKET,NAMED,RETRY,UNIX
unix-recvfrom:<filename> groups=FD,SOCKET,NAMED,CHILD,RETRY,UNIX
unix-sendto:<filename> groups=FD,SOCKET,NAMED,RETRY,UNIX
最終更新:2011年06月07日 02:42