跨进程通信: Unix Domain Socket 创建实例。 Windows和MacOS代码已适配兼容
一: 简介
具体使用到的
本文中的
由于 Windows 平台下的
二:Demo 展示
分别创建了两个命令行程序,分别为
都各自发送和接收了一条消息后退出程序
MacOS 控制台打印如下:

Windows 控制台打印如下:

三:代码
1. Server 代码
//
// main.cpp
// UDS_Server_cmd
//
// Created by jimbo on 2024/1/23.
//
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#ifdef _WIN32
#include <system_error>
#include <WS2tcpip.h>
#include <afunix.h>
#pragma warning(disable:4996)
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#endif // _WIN32
std::string s_sock_path;
#ifdef _WIN32
class SocketInit
{
public:
SocketInit() {
WSADATA data;
int ret = WSAStartup(MAKEWORD(2, 1), &data);
printf("WSAStartup val:%d
", ret);
}
~SocketInit() {
printf("~SocketInit
");
WSACleanup();
}
};
const SocketInit sInit;
#endif // _WIN32
// 创建临时 sock 文件
/*
win: C:UsersADMINI~1AppDataLocalTempjimbo_uds_test.sock
mac: /tmp/jimbo_uds_test.sock
*/
static void getScokTempPath() {
#ifdef _WIN32
wchar_t path[MAX_PATH + 1]{};
::GetTempPathW(_countof(path), path);
char sock_path_c[MAX_PATH + 1];
wcstombs(sock_path_c, path, MAX_PATH + 1);
std::string std_path(sock_path_c);
std_path += "jimbo_uds_server.sock";
s_sock_path = std_path;
#else
s_sock_path = "/tmp/jimbo_uds_test.sock";
#endif // _WIN32
printf("tmp path:%s
", s_sock_path.c_str());
//server 每次启动都要删除旧文件
if (remove(s_sock_path.c_str()) == -1 && errno != ENOENT)
{
printf("remove file failed.
");
exit(EXIT_FAILURE);
}
}
int main(int argc, char* argv[]) {
printf("
this is server!
");
getScokTempPath();
int client_fd;
client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (client_fd < 0) {
perror("socket connect failed");
exit(EXIT_FAILURE);
}
struct sockaddr_un addr = { 0 };
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, s_sock_path.c_str());
int ret = bind(client_fd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un));
if (ret < 0) {
perror("socket bind failed");
exit(EXIT_FAILURE);
}
printf("bind succeed!
");
ret = listen(client_fd, 5);
if (ret < 0) {
perror("socket listen failed");
exit(EXIT_FAILURE);
}
printf("listen succeed!
");
printf("waiting client....
");
client_fd = accept(client_fd, NULL, NULL);
printf("client connect succeed!
");
char buf[1024];
if (recv(client_fd, buf, 1024, 0) < 0) {
perror("socket recv failed");
exit(EXIT_FAILURE);
}
printf("server recv response: [%s]
", buf);
char buf1[] = "hello client, this msg is from server!";
if (send(client_fd, buf1, sizeof(buf1), 0) < 0) {
perror("socket send failed");
exit(EXIT_FAILURE);
}
printf("server send msg succeed!
");
#ifdef _WIN32
/* 关闭socket */
closesocket(client_fd);
#else
/* 关闭socket */
close(client_fd);
#endif // _WIN32
printf("server ended successfully
");
exit(EXIT_SUCCESS);
}
2. Client 代码
//
// main.cpp
// Uds_Client_cmd
//
// Created by jimbo on 2024/1/23.
//
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#ifdef _WIN32
#include <system_error>
#include <WS2tcpip.h>
#include <afunix.h>
#pragma warning(disable:4996)
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#endif // _WIN32
std::string s_sock_path;
#ifdef _WIN32
class SocketInit
{
public:
SocketInit() {
WSADATA data;
int ret = WSAStartup(MAKEWORD(2, 1), &data);
printf("WSAStartup val:%d
", ret);
}
~SocketInit() {
printf("~SocketInit
");
WSACleanup();
}
};
const SocketInit sInit;
#endif // _WIN32
// 创建临时 sock 文件
/*
win: C:UsersADMINI~1AppDataLocalTempjimbo_uds_test.sock
mac: /tmp/jimbo_uds_test.sock
*/
static void getScokTempPath() {
#ifdef _WIN32
wchar_t path[MAX_PATH + 1]{};
::GetTempPathW(_countof(path), path);
char sock_path_c[MAX_PATH + 1];
wcstombs(sock_path_c, path, MAX_PATH + 1);
std::string std_path(sock_path_c);
std_path += "jimbo_uds_server.sock";
s_sock_path = std_path;
#else
s_sock_path = "/tmp/jimbo_uds_test.sock";
#endif // _WIN32
printf("tmp path:%s
", s_sock_path.c_str());
}
int main(int argc, char* argv[]) {
printf("
this is client!
");
getScokTempPath();
int client_fd;
client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (client_fd < 0) {
perror("socket create failed");
exit(EXIT_FAILURE);
}
struct sockaddr_un addr = {0};
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, s_sock_path.c_str());
int ret = connect(client_fd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un));
if (ret < 0) {
perror("socket connect failed");
exit(EXIT_FAILURE);
}
printf("connect succeed!
");
char sendBuf[] = "hello server, this msg is from client!";
if (send(client_fd, sendBuf, sizeof(sendBuf), 0) < 0) {
perror("socket send failed");
exit(EXIT_FAILURE);
}
printf("send succeed!
");
char recvBuf[1024];
if (recv(client_fd, recvBuf, 1024, 0) < 0) {
perror("socket recv failed");
exit(EXIT_FAILURE);
}
printf("client recv response: [%s]
", recvBuf);
#ifdef _WIN32
/* 关闭socket */
closesocket(client_fd);
#else
/* 关闭socket */
close(client_fd);
#endif // _WIN32
printf("client ended successfully
");
exit(EXIT_SUCCESS);
}

