跨进程通信: Unix Domain Socket 创建实例。 Windows和MacOS代码已适配兼容
具体使用到的Socket
方法介绍可以查看 https://blog.csdn.net/goldWave01/article/details/135770238
本文中的 server
和 client
的代码可以直接 复制粘贴到 Windows 或 MacOS 的命令行程序中直接运行。
由于 Windows 平台下的 Unix Domain Socket
创建文章比较少,所以创建了这个demo。可直接在跨平台程序中使用。
分别创建了两个命令行程序,分别为 Server
和 Client
。
都各自发送和接收了一条消息后退出程序
MacOS
控制台打印如下:Windows
控制台打印如下://
// 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\n", ret);
}
~SocketInit() {
printf("~SocketInit\n");
WSACleanup();
}
};
const SocketInit sInit;
#endif // _WIN32
// 创建临时 sock 文件
/*
win: C:\Users\ADMINI~1\AppData\Local\Temp\jimbo_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\n", s_sock_path.c_str());
//server 每次启动都要删除旧文件
if (remove(s_sock_path.c_str()) == -1 && errno != ENOENT)
{
printf("remove file failed.\n");
exit(EXIT_FAILURE);
}
}
int main(int argc, char* argv[]) {
printf("\nthis is server!\n\n");
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!\n");
ret = listen(client_fd, 5);
if (ret < 0) {
perror("socket listen failed");
exit(EXIT_FAILURE);
}
printf("listen succeed!\n");
printf("waiting client....\n");
client_fd = accept(client_fd, NULL, NULL);
printf("client connect succeed!\n");
char buf[1024];
if (recv(client_fd, buf, 1024, 0) < 0) {
perror("socket recv failed");
exit(EXIT_FAILURE);
}
printf("server recv response: [%s]\n", 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!\n");
#ifdef _WIN32
/* 关闭socket */
closesocket(client_fd);
#else
/* 关闭socket */
close(client_fd);
#endif // _WIN32
printf("server ended successfully\n");
exit(EXIT_SUCCESS);
}
//
// 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\n", ret);
}
~SocketInit() {
printf("~SocketInit\n");
WSACleanup();
}
};
const SocketInit sInit;
#endif // _WIN32
// 创建临时 sock 文件
/*
win: C:\Users\ADMINI~1\AppData\Local\Temp\jimbo_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\n", s_sock_path.c_str());
}
int main(int argc, char* argv[]) {
printf("\nthis is client!\n\n");
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!\n");
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!\n");
char recvBuf[1024];
if (recv(client_fd, recvBuf, 1024, 0) < 0) {
perror("socket recv failed");
exit(EXIT_FAILURE);
}
printf("client recv response: [%s]\n", recvBuf);
#ifdef _WIN32
/* 关闭socket */
closesocket(client_fd);
#else
/* 关闭socket */
close(client_fd);
#endif // _WIN32
printf("client ended successfully\n");
exit(EXIT_SUCCESS);
}