広告
socatを使ってUNIXドメイン通信を中継し通信内容をのぞいてみる。
構成のイメージは下記。
1 2 3 4 5 6 7 8 9 |
-------------------------------------------------- ________ ________ ________ | | | | | | | Client |--->| socat |--->| Sever | |________| |________| |________| | ---> 標準出力に通信内容を表示。 -------------------------------------------------- |
プログラム
local.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdint.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <errno.h> #define MSGID_HELLO_REQUEST (0x0101) #define MAX_USER (1) typedef enum { MSG_KIND_REQUEST = 0, MSG_KIND_MAX } msgkind_t; typedef struct { uint32_t id; uint16_t kind; uint16_t seqno; } msg_header_t; |
client.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#include "local.h" #define UNIX_SOCKET_FILEPATH "./usocket.client" int main(void) { int sfd = -1; struct sockaddr_un addr = { .sun_family = AF_UNIX, .sun_path = UNIX_SOCKET_FILEPATH, }; sfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sfd < 0) { perror("socket"); exit(EXIT_FAILURE); } int rc = connect(sfd, (struct sockaddr* )&addr, sizeof(addr)); if (rc < 0) { perror("connect"); close(sfd); exit(EXIT_FAILURE); } uint16_t seqno = 0; while(1) { msg_header_t req = { .id = MSGID_HELLO_REQUEST, .kind = MSG_KIND_REQUEST, .seqno = seqno, }; ssize_t ss = send(sfd, (void*)&req, sizeof(req), 0); if (ss < 0) { perror("send"); close(sfd); break; } if (ss == 0 || ss < 0) { printf("connection closed.\n"); unlink(UNIX_SOCKET_FILEPATH); break; } printf("sent request, wait 3 sec (-.-)zzZ\n"); sleep(3); seqno++; } return 0; } |
server.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include "local.h" #define UNIX_SOCKET_FILEPATH "./usocket.server" int main(void) { int sfd = -1; struct sockaddr_un addr = { .sun_family = AF_UNIX, .sun_path = UNIX_SOCKET_FILEPATH, }; sfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sfd < 0) { perror("socket"); exit(EXIT_FAILURE); } unlink(UNIX_SOCKET_FILEPATH); int rc = bind(sfd, (struct sockaddr* )&addr, sizeof(addr)); if (rc < 0) { perror("bind"); close(sfd); exit(EXIT_FAILURE); } rc = listen(sfd, MAX_USER); if (rc < 0) { perror("listen"); close(sfd); exit(EXIT_FAILURE); } socklen_t addrlen; struct sockaddr_un caddr; int acsfd = accept(sfd, (struct sockaddr *)&caddr, &addrlen); if (acsfd < 0) { perror("accept"); close(sfd); exit(EXIT_FAILURE); } while(1) { uint16_t seqno = 0; msg_header_t req; ssize_t rs = recv(acsfd, (void*)&req, sizeof(req), 0); if (rs < 0) { perror("recv"); close(sfd); break; } printf("recv size=%d, id=%#x, kind=%#x, seqno=%d\n", rs, req.id, req.kind, req.seqno); if (rs == 0) { printf("connection closed.\n"); unlink(UNIX_SOCKET_FILEPATH); break; } } return 0; } |
実行結果
3つの端末を開き各端末で下記コマンドを実行。
1 2 |
$ sudo yum -y install socat $ socat -x -v UNIX-LISTEN:./usocket.client, UNIX-CONNECT:./usocket.server |
1 2 |
$ gcc -o server server.c $ ./server |
1 2 |
$ gcc -o client client.c $ ./client |
広告
広告