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

AF_UNIX套接字客户端服务端程序报错求助:传输端点未连接

解决AF_UNIX抽象套接字UDP客户端-服务端的连接与发送问题

看起来你碰到了AF_UNIX套接字(尤其是抽象命名空间+UDP组合)的几个典型坑,我来帮你拆解下问题原因和具体解决思路:

1. "transport endpoint not connected" 错误的原因与解决

这个错误在UDP套接字里非常常见,核心原因是:

  • UDP是无连接协议,如果你直接调用send()而不是sendto(),系统不知道要把数据发往哪个地址——send()要求你预先通过connect()绑定对端的地址。
  • 如果你没做connect(),就必须用sendto(),每次调用时明确指定目标套接字的地址结构。

2. Linux抽象套接字SOCK_DGRAM拒绝连接的问题

这个问题大多是因为抽象套接字的使用规则没搞对,核心注意点:

  • 抽象套接字必须以空字节\0开头:这是它和普通文件系统套接字的核心区别,很多人会漏掉这个,导致服务端绑定的地址和客户端要连接的地址不匹配,自然会拒绝连接。
  • 绑定地址的长度计算要正确:不能直接用sizeof(struct sockaddr_un),而是要计算到抽象名字的末尾。比如你的抽象名字是"\0my_socket",地址长度应该是offsetof(struct sockaddr_un, sun_path) + strlen("\0my_socket" + 1) + 1(跳过开头的\0计算名字长度,再加1包含那个开头的\0)。
  • 服务端必须先完成bind再接收/客户端连接:UDP服务端必须先调用bind()绑定到抽象地址,客户端才能成功connect()或者sendto(),否则会出现连接拒绝。

给你一份可运行的示例代码

服务端代码(SOCK_DGRAM + 抽象套接字)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

// 抽象套接字必须以\0开头
#define ABSTRACT_SOCKET "\0my_abstract_udp_socket"

int main() {
    int sockfd;
    struct sockaddr_un server_addr;

    // 创建UDP套接字
    if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 初始化地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strncpy(server_addr.sun_path, ABSTRACT_SOCKET, sizeof(server_addr.sun_path)-1);

    // 计算抽象套接字的地址长度
    socklen_t addr_len = offsetof(struct sockaddr_un, sun_path) + (strlen(ABSTRACT_SOCKET + 1) + 1);

    // 绑定到抽象地址
    if (bind(sockfd, (struct sockaddr*)&server_addr, addr_len) == -1) {
        perror("bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("UDP server listening on abstract socket...\n");

    char buffer[1024];
    ssize_t recv_len;
    struct sockaddr_un client_addr;
    socklen_t client_len = sizeof(client_addr);

    // 循环接收客户端数据
    while ((recv_len = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&client_addr, &client_len)) != -1) {
        buffer[recv_len] = '\0';
        printf("Received from client: %s\n", buffer);
    }

    perror("recvfrom failed");
    close(sockfd);
    return 0;
}

客户端代码(两种发送方式可选)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

#define ABSTRACT_SOCKET "\0my_abstract_udp_socket"

int main() {
    int sockfd;
    struct sockaddr_un server_addr;

    // 创建UDP套接字
    if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 初始化服务端地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strncpy(server_addr.sun_path, ABSTRACT_SOCKET, sizeof(server_addr.sun_path)-1);
    socklen_t addr_len = offsetof(struct sockaddr_un, sun_path) + (strlen(ABSTRACT_SOCKET + 1) + 1);

    // 方式1:先connect,之后用send发送(适合多次发送)
    if (connect(sockfd, (struct sockaddr*)&server_addr, addr_len) == -1) {
        perror("connect failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    const char* msg = "Hello from UDP client!";
    if (send(sockfd, msg, strlen(msg), 0) == -1) {
        perror("send failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 方式2:不用connect,直接用sendto发送(适合单次或目标不固定的发送)
    /*
    const char* msg = "Hello from UDP client!";
    if (sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&server_addr, addr_len) == -1) {
        perror("sendto failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    */

    printf("Message sent successfully\n");
    close(sockfd);
    return 0;
}

最后再强调几个关键点

  • 编译时记得直接用gcc编译即可,比如gcc server.c -o server,gcc client.c -o client。
  • 先启动服务端,再运行客户端,否则客户端会提示连接拒绝。
  • 抽象套接字不会在文件系统中生成文件,所以不用手动清理,进程退出后会自动释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:59:30