【问题标题】:Why does using a file descriptor of the family AF_UNIX cause accept() to give an "invalid argument" error?为什么使用 AF_UNIX 系列的文件描述符会导致 accept() 给出“无效参数”错误?
【发布时间】:2025-12-24 20:10:09
【问题描述】:

这给了我一个无效的参数错误:

int listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
*clientfdp = accept(listenfd, (SA *) &clientAddr, &clientLen);

虽然没有

int listenfd = socket(AF_INET, SOCK_STREAM, 0);
*clientfdp = accept(listenfd, (SA *) &clientAddr, &clientLen);

但我需要它是AF_UNIX。这是怎么回事?我也检查了所有地方的错误。 socket() 的输出在任何一种情况下都很好,只是在accept 期间。

这里是完整的代码:

// forward declarations
int error_msg( char * msg );
int usage( char name[] );

// a function to be executed by each thread
void * recv_log_msgs( void * arg );

// globals
FILE * log_fd; // opened by main() but accessible by each thread
typedef struct sockaddr SA;

int error_msg( char * msg )
{
    printf( "%s\n", msg );
    return -1;
}

void * recv_log_msgs( void * arg ) //Thread Routine
{
    // loops to receive messages from a client;
    // when the connection is closed by the client,
    // close the socket
    int clientfd = *((int *)arg);
    char buffer[1500];
    memset(buffer, 0, 1500);
    int currentPos = 0;
    int bytesRec;
    int recvng = 1;

    while(recvng){
        bytesRec = recv(clientfd, buffer, 1500-currentPos, 0);
        currentPos += bytesRec;
        if(buffer[currentPos - 1] == '\n')
            recvng = 0;
    }

    fprintf(log_fd, "LOGGER %d %s", clientfd, buffer);
    close(clientfd);
    return NULL;
}

int usage( char name[] )
{
    printf( "Usage:\n" );
    printf( "\t%s <log-file-name> <UDS path>\n", name );
    return 1;
}

int main( int argc, char * argv[] )
{
    if ( argc != 3 )
        return usage( argv[0] );

    log_fd = fopen(argv[1], "a");

    // create a server socket
    // domain (i.e., family) is AF_UNIX
    // type is SOCK_STREAM

    socklen_t clientLength = sizeof(struct sockaddr_un);
    struct sockaddr_un clientAddr;
    clientAddr.sun_family = AF_UNIX;
    strcpy(clientAddr.sun_path, argv[2]);

    pthread_t tid;

    int listenfd = socket(AF_UNIX, SOCK_STREAM, 0);     

    // unlink the UDS path)
    unlink(argv[2]);

    // bind the server socket
    bind(listenfd, (SA *)&clientAddr, clientLength);    

    // listen
    listen(listenfd, 1024);
    // loop to wait for connections;
    // as each connection is accepted,
    // launch a new thread that calls
    // recv_log_msgs(), which receives
    // messages and writes them to the log file
    while(1){
        printf( "Waiting for a connection on UDS path %s...\n", argv[2] );
        int * clientfdp = malloc(sizeof(int));
        *clientfdp = accept(listenfd, (SA *) &clientAddr, &clientLength);
        pthread_create(&tid, NULL, recv_log_msgs, clientfdp);
        printf("%d",errno);
        return 0;
    }

    // when the loop ends, close the listening socket
    close(listenfd);        

    // close the log file
    fclose(log_fd);

    return 0;
}

【问题讨论】:

  • 什么是clientAddr?它是如何初始化的? clientLen 是什么?以及它是如何初始化的? SA 是什么?请尝试创建Minimal, Complete, and Verifiable Example 并展示给我们。
  • @JoachimPileborg 我知道这些都不是问题。如果我如上所示更改listenfd,那么一切都很好。但无论如何我都会更新帖子。
  • @JoachimPileborg 我已经编辑了帖子以包含所有代码,但是是的,我也更改了 clientAddr,如编辑中所示。我不知道是什么问题。
  • 不幸的是,您没有像您声称的那样在所有地方检查错误。请添加对 bind() 和 listen() 成功的检查。如果它们失败,您的 accept() 调用将按照您的描述失败。
  • 您确定在bind 调用地址中使用的文件不存在吗?你有创建文件的权限吗?从中读取?给它写信?路径有效吗?

标签: c multithreading sockets


【解决方案1】:

调用pthread_create()后main()函数调用pthread_join()失败

结果是进程在线程有机会写入日志文件之前退出。

【讨论】:

    最近更新 更多