C だとお決まりの socket bind listen accept で作る。以下同時接続数 1 の echo サーバ。
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> int main() { int sock; struct sockaddr_un addr; if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { perror("socket"); return 1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = PF_UNIX; strcpy(addr.sun_path, "/tmp/hoge"); if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } if (listen(sock, 1) < 0) { perror("listen"); return 1; } while (1) { struct sockaddr_un dummy; int fd; int len = sizeof(dummy); if ((fd = accept(sock, (struct sockaddr*)&dummy, &len)) < 0) { perror("accept"); return 1; } while (1) { int ret; char c; ret = read(fd, &c, 1); if (ret < 0) { perror("read"); return 1; } else if (ret == 0) { break; } write(fd, &c, 1); } close(fd); } }
はしょって書いたのに長いな…これでも同時接続できないし。 Ruby は UNIXServer なるクラスを使うとほとんど TCPServer と同じでラク。
require 'socket' USOCK = '/tmp/hoge' if File.exist? USOCK File.unlink USOCK end UNIXServer.open(USOCK) do |serv| while true s = serv.accept while true c = s.getc if c s.putc c else break end end end end
こんくらいだとちゃんとスレッド作って同時接続対応とかしてやってもいい気がしてきます。
でもまぁもっとラクな方法があって、 Ubuntu だと ucspi-unix ってパッケージに入ってる unixserver コマンドを使うと
unixserver /tmp/hoge cat
で終わり。ちゃんと終了時にソケット削除してくれるし良い。接続数設定とかもできるし。要は tcpserver とかみたいに標準入出力とやりとりするコマンドがなんでもサーバになってくれるわけ。なんか tcpserver が手元に入ってないと気付いたので tcpsvd とやらで代用すると、
tcpsvd 0 9999 cat
とかとおなじ。