跨进程通信: 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); }