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

使用PF_UNIX/AF_UNIX套接字实现父子进程通信时遇传输端点未连接错误

解决AF_UNIX套接字通信的"transmission endpoint not connected"错误

我一眼就揪出了问题的核心,咱们一步步拆解清楚:

错误根源:用错了套接字描述符

你在父进程里调用send(father_desc, ...),但father_desc是监听套接字(通过socket()+bind()+listen()创建的),它的唯一作用就是调用accept()等待并接受新连接。真正用来和子进程收发数据的,是accept()返回的那个已连接套接字——也就是你的son1_desc!

这就好比你开了个门店(监听套接字),有人上门(子进程发起connect),你得把客人带到会客室(已连接套接字)才能聊天,总不能直接在门店门口喊话对吧?

其他需要修正的潜在问题

除了这个核心错误,代码里还有几个小问题会导致通信异常:

  • 父进程的wait(NULL)时机不对:第一个wait会直接等待第一个子进程结束,但此时父进程还没启动socket服务,第一个子进程的connect大概率会失败(哪怕sleep了1秒,也可能赶不上父进程的bind/listen流程)。应该把父进程的socket初始化逻辑放在fork子进程之前。
  • recv的长度参数错误:你用了strlen(message)+1,但message初始是空字符串,strlen(message)是0,这意味着你最多只接收1字节数据,根本拿不到完整消息。应该用缓冲区的总大小(比如sizeof(message)-1,留一个字节给终止符)。
  • 第二个子进程没有任何逻辑,会直接退出,不过这暂时不影响第一个子进程的通信。

修正后的完整代码

我把所有问题都修复了,关键修改处用注释标出来了:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/un.h>
#include <string.h>  // 别忘了包含string.h,strlen需要它

#define PATH "/tmp/Server"

int main() {
    pid_t proc1, proc2;

    // 先初始化父进程的socket服务,再fork子进程,避免子进程connect时服务还没启动
    int father_desc = socket(PF_UNIX, SOCK_STREAM, 0);
    if (father_desc == -1) {
        perror("Errore nel socket padre");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_un father_add = {AF_UNIX, PATH};
    unlink(PATH);  // 先删除旧的套接字文件,避免bind失败
    if (-1 == bind(father_desc, (struct sockaddr*)&father_add, sizeof(struct sockaddr_un))) {
        perror("Errore nel bind");
        close(father_desc);
        exit(EXIT_FAILURE);
    }

    if (-1 == listen(father_desc, 2)) {
        perror("Errore nel listen");
        close(father_desc);
        exit(EXIT_FAILURE);
    }

    // 现在再fork子进程
    proc1 = fork();
    if(proc1 == -1) {
        perror("Errore nella prima fork");
        close(father_desc);
        exit(EXIT_FAILURE);
    }

    if(proc1 != 0) {
        // PADRE DOPO IL PRIMO FIGLIO
        proc2 = fork();
        if(proc2 == -1) {
            perror("Errore nella seconda fork");
            close(father_desc);
            wait(NULL);
            exit(EXIT_FAILURE);
        }

        if(proc2 != 0) {
            // PADRE DOPO I DUE FIGLI
            struct sockaddr_un son1_add;
            int len = sizeof(son1_add);
            int son1_desc = accept(father_desc, (struct sockaddr*)&son1_add, &len);
            if(-1 == son1_desc) {
                perror("Errore nell'accept");
                close(father_desc);
                wait(NULL);
                wait(NULL);
                exit(EXIT_FAILURE);
            }

            char message[256] = "Ciao";
            // 关键修改:用son1_desc(已连接套接字)发送数据,而不是father_desc
            if(-1 == send(son1_desc, message, strlen(message) + 1, 0)) {
                perror("Errore nel send");
                close(father_desc);
                close(son1_desc);
                wait(NULL);
                wait(NULL);
                exit(EXIT_FAILURE);
            }

            close(father_desc);
            close(son1_desc);
            wait(NULL);  // 等待第一个子进程
            wait(NULL);  // 等待第二个子进程
            unlink(PATH);  // 通信结束后删除套接字文件
        } else {
            // SECONDO FIGLIO - 可以在这里添加第二个子进程的通信逻辑
            sleep(2);
            printf("Secondo figlio terminato\n");
            exit(EXIT_SUCCESS);
        }
    } else {
        // PRIMO FIGLIO
        struct sockaddr_un son1_add = {AF_UNIX, PATH};
        int son1_desc = socket(PF_UNIX, SOCK_STREAM, 0);
        if(-1 == son1_desc) {
            perror("Errore nel socket figlio");
            exit(EXIT_FAILURE);
        }

        // 加个重试逻辑,避免父进程还没准备好
        int retries = 5;
        while (retries-- > 0) {
            if (-1 == connect(son1_desc, (struct sockaddr*) &son1_add, sizeof(struct sockaddr_un))) {
                perror("Tentativo connect fallito, riprovo...");
                sleep(1);
            } else {
                break;
            }
        }
        if (retries < 0) {
            perror("Errore nel connect dopo più tentativi");
            close(son1_desc);
            exit(EXIT_FAILURE);
        }

        char message[256] = "";
        // 关键修改:用sizeof(message)-1作为接收长度,确保能拿到完整消息
        if(-1 == recv(son1_desc, message, sizeof(message)-1, 0)) {
            perror("Errore nel rcv");
            close(son1_desc);
            exit(EXIT_FAILURE);
        }
        printf("Messaggio ricevuto dal padre: %s\n", message);

        close(son1_desc);
        exit(EXIT_SUCCESS);
    }

    return 0;
}

验证修改后的效果

编译运行后,第一个子进程会成功接收到父进程发送的"Ciao",不会再出现"transmission endpoint not connected"错误。

内容的提问来源于stack exchange,提问作者Tom Riddle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:08:34