前書き
これは第17章、プロセス同期用のUnixドメインソケットです。前回の記事では、共有メモリを介したプロセス同期の問題を紹介しました。この記事は、プロセス同期を実現するためのもう1つの方法であるUnixドメインソケットです。
Unixドメインソケット
- ドメインソケットは、プロセス間通信の高度な方法です。
- Unixドメインソケットは、同じマシンでのプロセス間通信に使用できます
- ソケットはもともとネットワーク通信で使用される用語でした
- Unixシステムが提供するドメインソケットは、ネットワークソケットと同様の機能を提供します
共有メモリには、複数のプロセス間の通信を同期するための追加の同期メカニズムが必要であることを以前に学びました。Unixドメインソケットは、複数のプロセス間の通信を確保するために追加のメカニズムを必要としません(実際、Nginxをデプロイするときは、unixドメインソケットを使用します)
Unixドメインソケットの使用方法
:サーバーは左側にあり、クライアントは右側にあります
以下はコード例です。クライアントとサーバーはドメインソケットを介して接続されています
サーバー(server.cpp)
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<strings.h>
#include<string.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<iostream>
//定义域套接字路径
//使用域套接字时,它会在文件系统中创建一个文件,客户端和服务端就是通过这个文件进行连接
#define SOCKET_PATH "./domainsocket"
//定义消息最大长度
#define MSG_SIZE 2048
int main()
{
int socket_fd,accept_fd;
int ret = 0;
socklen_t addr_len;
char msg[MSG_SIZE];
struct sockaddr_un server_addr;
//1.创建域套接字
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (-1 == socket_fd) {
std::cout << "Socket create failed" << std::endl;
return -1;
}
//移除已有域套接字路径
remove(SOCKET_PATH);
//内存区域设置为0
bzero(&server_addr, sizeof(server_addr));
server_addr.sun_family = PF_UNIX;
strcpy(server_addr.sun_path, SOCKET_PATH);
//2.绑定域套接字
std::cout << "Binding socket..." << std::endl;
ret = bind(socket_fd, (sockaddr *)&server_addr, sizeof(server_addr));
if (0 > ret) {
std::cout << "Bind socket failed." << std::endl;
return -1;
}
//3.监听套接字
std::cout << "Listening socket..." << std::endl;
ret = listen(socket_fd, 10);//数字为监听连接的大小
if(-1 == ret) {
std::cout << "Listen failed" << std::endl;
}
std::cout << "Waiting new request." << std::endl;
accept_fd = accept(socket_fd, NULL, NULL);
bzero(msg, MSG_SIZE);
while(true) {
//4.接收&处理信息
recv(accept_fd, msg, MSG_SIZE, 0);
std::cout << "Received message from remote: " << msg << std::endl;
}
close(accept_fd);
close(socket_fd);
return 0;
}
クライアント(client.cpp)
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<strings.h>
#include<string.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<unistd.h>
#include<iostream>
//定义域套接字路径
//使用域套接字时,它会在文件系统中创建一个文件,客户端和服务端就是通过这个文件进行连接
#define SOCKET_PATH "./domainsocket"
//定义消息最大长度
#define MSG_SIZE 2048
int main()
{
int socket_fd;
int ret = 0;
char msg[MSG_SIZE];
struct sockaddr_un serve_addr;
//1.创建域套接字
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (-1 == socket_fd) {
std::cout << "Socket create failed" << std::endl;
return -1;
}
//内存区域设置为0
bzero(&server_addr, sizeof(server_addr));
server_addr.sun_family = PF_UNIX;
strcpy(server_addr.sun_path, SOCKET_PATH);
//2.连接域套接字
ret = connect(socket_fd, (sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret) {
std::cout << "Connect socket failed" << std::endl;
return -1;
}
while(true) {
std::cout << "Input message>>>";
fgets(msg, MSG_SIZE, stdin);
//3.发送信息
ret = send(socket_fd, msg, MSG_SIZE, 0);
}
close(socket_fd);
return 0;
}
server.cppを実行します
cliet.cppを実行し、メッセージを送信します
サーバーはメッセージを受信します
ドメインソケットは、信頼性の高い情報転送を提供します。共有メモリと比較して、複数のプロセスがメモリ空間を読み取るためのメカニズムを維持する必要はありません。つまり、共有メモリと比較して、ドメインソケットの信頼性は高くなります。コードから、クライアントとサーバーが通信する場合、同期メカニズムを管理するために追加のタグは不要であり、使用が簡単であることがわかります。
総括する
- 単一のマシンにシンプルで信頼性の高いプロセス通信同期サービスを提供します
- 単一のマシンでのみ使用でき、マシン間では使用できません(クロスマシンにはネットワークソケットが必要です)
急速に変化するテクノロジーの常識を見つけることは、技術者のコアコンピタンスです。理論と実践を組み合わせた知識と行動の統一