UbuntuのTerminalでUnix Domain Socketを使ってIPCするC言語実装の最小構成サンプル
今回のサンプルを実装した元々の目的はAndroid NativeでのSocketを使ったIPCの概要をざっくり知ることでした.
TL;DR (長い三行で)
実装はServer側とClient側の2種類,.c 2ファイル.
.cをgccでCompileして実行Fileを2つ出力.
それぞれ別Terminal(別Process)上で実行し,文字列メッセージを送受信する.
Socketの種類
Socket自体は通信方式やProtocolの実装は規定していないようで,今回のような同一Host内のIPCでも,他Host間のTCP/IP等の通信も可能になっているようです.
今回は同一Host内のIPCをSocketをつかって実装します.
Build方法
gccを使って.cを実行Fileにcompileします.
今回のサンプルは実装が超シンプルなので,何のOption指定もしなくても試すことはできます.
(gccとかに詳しい人には怒られそうですが...)
# Current Dirのserver.cというファイルをCompileしてserverという実行Fileを出力
$ gcc -o server server.c
# 出力した実行Fileを実行
$ ./server
Server側実装
Server側は起動後,接続を待ち続け,接続が来たらデータを読み取り,終わったらまた接続を待つ,という処理になります.
Server側はずっと動き続けるものになるので,終了させるときはctrl+c
とかで強制終了するか,Clientからの終了コマンドを定義するか,が必要です.
socket // Socket自身のFile Descriptor作成
↓
sockadddr_un // Socket接続待ちのAddress (Socket File) を指定
↓
bind // SocketをSocket Fileに接続
↓
listen // Socketを受信待ちSocketに指定
↓
accept // Clientからの接続を受け付け
↓
read // ClientからのDataを受信
↓
close // Clientから受信したFile DescriptorをClose
↓
close // Socket自身のFile DescriptorをClose
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
void on_error(char* msg, int socket_fd) {
if (socket_fd != -1) {
close(socket_fd);
}
printf("TraceLog: server: %s\n", msg);
}
int main(void) {
printf("TraceLog: server: main() : E\n");
int err = 0;
int socket_fd = -1;
// Create server socket file discriptor.
socket_fd = socket(
AF_UNIX, // Local connection.
SOCK_STREAM, // Bi-directional access, bite stream.
0); // Default protocol.
if (socket_fd == -1) {
on_error("socket_fd != 0", socket_fd);
return -1;
}
// Struct for socket address.
struct sockaddr_un addr = { 0 }; // 0 init.
addr.sun_family = AF_UNIX; // Fixed.
strcpy(addr.sun_path, "socket_file"); // Common socket file.
// Remove old socket. If file exists, bind will be failed.
remove(addr.sun_path);
// Bind.
err = bind(
socket_fd, // Bind target socket.
(struct sockaddr*) &addr, // Socket address.
sizeof(struct sockaddr_un)); // Address size.
if (err != 0) {
on_error("bind failed.", socket_fd);
return -1;
}
// Mark passive socket.
err = listen(
socket_fd, // Target socket.
1); // Max connection count.
if (err != 0) {
on_error("listen failed.", socket_fd);
return -1;
}
// Wait for connection and receive.
while(1) {
// Wait for client connection.
int fd = accept(
socket_fd, // Target socket.
NULL, // Client address.
NULL); // Client address size.
if (fd == -1) {
on_error("accept failed.", socket_fd);
return -1;
}
// Receive.
char buffer[256];
int size = read(
fd, // Accepted fd.
buffer, // Receive buffer.
sizeof(buffer) - 1); // Receive size. Last byte is null char.
if (size == -1) {
on_error("read failed.", socket_fd);
return -1;
}
// Output received message.
buffer[size] = '\0';
printf("TraceLog: server: Received Msg = %s\n", buffer);
// Close client fd.
err = close(fd); // Closed client connection fd.
if (err != 0) {
on_error("close fd failed.", socket_fd);
return -1;
}
} // while(true)
// Close server socket.
close(socket_fd);
printf("## server main() : X\n");
return 0;
}
Client側実装
Client側の処理は接続先のSocket(Socket File)に対して接続,接続完了したらデータ送信,の流れです.
socket // Socket自身のFile Descriptor作成
↓
sockadddr_un // Socket接続先のAddress (Socket File) を指定
↓
connect // SocketをSocket Fileに接続している別のSocketに接続
↓
write // 接続先SocketにDataを送信
↓
close // Socket自身のFile DescriptorをClose
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#define MESSAGE "HELLO WORLD !"
void on_error(char* msg, int socket_fd) {
if (socket_fd != -1) {
close(socket_fd);
}
printf("TraceLog: client: %s\n", msg);
}
int main(void) {
printf("TraceLog: client: main() : E\n");
int err = 0;
int socket_fd = -1;
// Create client socket.
socket_fd = socket(
AF_UNIX, // Local connection.
SOCK_STREAM, // Bi-directional access, bite stream.
0); // Default protocol.
if (socket_fd == -1) {
on_error("socket_fd != 0", socket_fd);
return -1;
}
// Struct for socket address.
struct sockaddr_un addr = { 0 }; // 0 init.
addr.sun_family = AF_UNIX; // Fixed.
strcpy(addr.sun_path, "socket_file"); // Common socket file.
// Connect.
err = connect(
socket_fd, // Bind target socket.
(struct sockaddr*) &addr, // Socket address.
sizeof(struct sockaddr_un)); // Address size.
if (err != 0) {
on_error("connect failed.", socket_fd);
return -1;
}
// Send message.
err = write(
socket_fd, // Target socket.
MESSAGE, // Message.
strlen(MESSAGE)); // Message size.
if (err == -1) {
on_error("write failed.", socket_fd);
return -1;
}
// Close client socket.
close(socket_fd);
printf("TraceLog: client: main() : X\n");
return 0;
}
動作確認
- Server用Terminalで
./server
を打ちServerを起動,接続待ち状態にする
- Client用Terminalで
./client
を打ちClientを起動,メッセージ送信後,自動で終了
- Server用TerminalにClientからのメッセージが表示されていることを確認
おわり
./server
を打ちServerを起動,接続待ち状態にする./client
を打ちClientを起動,メッセージ送信後,自動で終了Author And Source
この問題について(UbuntuのTerminalでUnix Domain Socketを使ってIPCするC言語実装の最小構成サンプル), 我々は、より多くの情報をここで見つけました https://qiita.com/fezrestia/items/b26c5b6d769c4c35ce42著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .