Windows与Linux的命名管道不兼容,应分别使用CreateNamedPipeA和AF_UNIX socket;需隔离路径命名、安全创建socket、设置非阻塞I/O、自定义消息头保边界,并完善错误恢复逻辑。

Windows 和 Linux 下 named pipe 不能混用,别硬套同一套代码
Windows 的 CreateNamedPipeA 和 Linux 的 mkfifo 名字看着像,但底层协议、路径语义、权限模型全都不兼容。直接把 Windows 上用 \.pipemyapp 写的代码扔到 Linux 上跑,会卡在 open 或 connect 返回 -1,errno 是 ENOENT 或 EACCES。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 跨平台项目里,
named pipe只在 Windows 上用,Linux 上必须切到AF_UNIXsocket - 路径命名要隔离:Windows 用
\\.\pipe\myapp_v1,Linux 用/tmp/myapp_v1.sock(避免用/var/run,普通用户没权限) - 不要依赖
boost::interprocess的named_mutex那套抽象——它底层在 Windows 用命名对象,在 Linux 用shm_open+mmap,和 IPC 通道无关
AF_UNIX socket 在 Linux/macOS 上怎么安全创建和清理
Unix domain socket 不是文件,但用文件系统路径做地址,这就带来两个坑:残留 socket 文件导致 bind 失败;没设好权限导致其他用户能连上来。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 每次
bind前先unlink路径,哪怕失败也无所谓:unlink("/tmp/myapp.sock");不加这句,重启进程大概率报EADDRINUSE -
chmod必须跟上:chmod("/tmp/myapp.sock", 0600),否则默认可能是 0644,任何本地用户都能 connect - 服务端
listen后,客户端连不上?检查sizeof(sockaddr_un)是否传对了——Linux 要用offsetof(struct sockaddr_un, sun_path) + strlen(path),不是整个结构体大小
C++ 里怎么写可中断的 connect 和 recv,避免卡死
IPC 通道一旦阻塞,又没超时机制,整个线程就挂住。Windows 的 ConnectNamedPipe 默认同步,Linux 的 connect 默认也阻塞,recv 更是经典卡点。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- Windows:用
CreateEvent+ConnectNamedPipe异步模式,再配合WaitForMultipleObjects等待事件或超时 - Linux:socket 创建后立刻
fcntl(fd, F_SETFL, O_NONBLOCK),然后用poll或epoll_wait等待可写(connect 完成)或可读(recv 有数据) - 别用
std::this_thread::sleep_for轮询——CPU 白耗,延迟还高;也别信“只设SO_RCVTIMEO就够了”,它对connect无效
消息边界怎么保?别指望 send/recv 自动分包
不管是 named pipe 还是 AF_UNIX socket,底层都是字节流(stream),不是消息队列。你 send 三次 100 字节,对方 recv 一次可能拿到 300 字节,也可能只拿到 127 字节,下一次才拿到剩下的。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 必须自己加消息头:前 4 字节存
uint32_t表示 body 长度,接收方先recv4 字节,再循环recv直到凑够 body 长度 - 别用
