You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CentOS 7与Windows跨平台NamedPipe读写失败问题求助

跨Windows与CentOS 7实现命名管道读写的解决方案

问题根源

Linux用mkfifo创建的是本地文件系统级别的命名管道,仅支持同一主机内的进程间通信,无法被Windows直接通过CreateFile或open跨网络访问——两者的命名管道实现机制完全不兼容,这是你读操作失败的核心原因。

可行解决方案

方案一:用TCP套接字模拟跨主机"命名管道"

这是最通用的跨主机进程通信方式,通过TCP连接传输数据,两端分别封装读写逻辑,模拟命名管道的使用体验。

CentOS端代码(读取本地FIFO并转发到Windows)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>

#define PORT 8080
#define FIFO_PATH "./fifo1"

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    int fifo_fd;

    // 创建TCP套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 设置端口复用
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // 绑定并监听端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    // 等待Windows客户端连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    // 打开本地FIFO(需确保已有写入进程打开FIFO,否则会阻塞)
    fifo_fd = open(FIFO_PATH, O_RDONLY);
    if (fifo_fd < 0) {
        perror("open fifo failed");
        close(new_socket);
        exit(EXIT_FAILURE);
    }

    // 读取FIFO内容并发送到Windows
    ssize_t bytes_read;
    while ((bytes_read = read(fifo_fd, buffer, sizeof(buffer)-1)) > 0) {
        send(new_socket, buffer, bytes_read, 0);
        memset(buffer, 0, sizeof(buffer));
    }

    close(fifo_fd);
    close(new_socket);
    close(server_fd);
    return 0;
}
Windows端代码(从CentOS接收数据)
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>

#define PORT 8080
#define CENTOS_IP "192.168.1.100" // 替换为你的CentOS主机IP

#pragma comment(lib,"ws2_32.lib")

int main() {
    WSADATA wsa;
    SOCKET sock;
    struct sockaddr_in server;
    char buffer[1024];
    int recv_size;

    // 初始化Winsock
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) {
        printf("WSAStartup失败,错误码: %d",WSAGetLastError());
        return 1;
    }

    // 创建套接字
    if((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        printf("创建套接字失败,错误码: %d", WSAGetLastError());
    }

    server.sin_addr.s_addr = inet_addr(CENTOS_IP);
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);

    // 连接到CentOS服务器
    if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
        puts("连接失败");
        return 1;
    }

    puts("已连接");

    // 循环读取数据
    while((recv_size = recv(sock, buffer, sizeof(buffer)-1, 0)) > 0) {
        buffer[recv_size] = '\0';
        printf("收到数据: %s\n", buffer);
        memset(buffer, 0, sizeof(buffer));
    }

    if (recv_size == 0) {
        puts("连接已关闭");
    } else if (recv_size == SOCKET_ERROR) {
        printf("接收数据失败,错误码: %d", WSAGetLastError());
    }

    closesocket(sock);
    WSACleanup();
    return 0;
}
注意事项
  1. CentOS端需先开放8080端口:
    firewall-cmd --add-port=8080/tcp --permanent
    firewall-cmd --reload
    
  2. 确保CentOS的FIFO已有写入进程打开(比如用echo "test" > fifo1保持写入端打开),否则读操作会阻塞。

方案二:通过Samba共享实现Windows风格命名管道

如果希望使用Windows原生的命名管道API,可通过Samba在CentOS上暴露共享目录及命名管道:

  1. 安装Samba服务:
    yum install samba samba-client -y
    
  2. 修改/etc/samba/smb.conf,添加共享配置:
    [pipe-share]
        path = /your/fifo/directory
        public = yes
        writable = yes
        printable = no
        create mask = 0666
        directory mask = 0777
        allow pipe = yes
    
  3. 创建Samba用户并设置密码:
    smbpasswd -a your-username
    
  4. 重启Samba服务:
    systemctl restart smb
    
  5. Windows端使用UNC路径访问FIFO:\\CentOS-IP\pipe-share\fifo1,调用CreateFile进行读写。

注意:Samba对Linux FIFO的兼容性有限,需确保FIFO两端的读写进程同时处于活跃状态,否则可能出现阻塞或读取失败。

内容的提问来源于stack exchange,提问作者Gautam Saini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 05:15:35