带有select()的recvfrom()上的UNIX域数据报套接字块

带有select()的recvfrom()上的UNIX域数据报套接字块,c,linux,sockets,C,Linux,Sockets,我使用UNIX域数据报套接字在多线程程序中将记录从多个客户端发送到单个服务器。一切都是在一个过程中完成的;我将记录从多个线程发送到充当服务器的单个线程。所有线程都使用其关联掩码分配给单独的核心 我的问题是,当我使用select从套接字缓冲区中包含记录的客户端套接字检索记录时。我使用的是与单个客户端套接字相同的基本设置,它在该上下文中工作,但现在它显然挂起,当我调用recvfrom时,它会阻塞。这是令人惊讶的,因为select函数已经将套接字标识为可用于读取 int select_clientso

我使用UNIX域数据报套接字在多线程程序中将记录从多个客户端发送到单个服务器。一切都是在一个过程中完成的;我将记录从多个线程发送到充当服务器的单个线程。所有线程都使用其关联掩码分配给单独的核心

我的问题是,当我使用select从套接字缓冲区中包含记录的客户端套接字检索记录时。我使用的是与单个客户端套接字相同的基本设置,它在该上下文中工作,但现在它显然挂起,当我调用recvfrom时,它会阻塞。这是令人惊讶的,因为select函数已经将套接字标识为可用于读取

int select_clientsockets(int64_t srvrfd, int64_t * claddr, int fds_array[], int fd_count, void * recvbuf){

    int fds_ready;
    int abc;
    int64_t cli_addr;

    FD_ZERO(&fdset);
    FD_SET(0,&fdset);

    socklen_t * len = (socklen_t * ) sizeof(struct sockaddr_un);

    fds_ready = select(3, &fdset, NULL, NULL, 0);

    for (int i = 0; i < fd_count; i++){

        fds_array[i] = 0;

        if (FD_ISSET(i, &fdset)) {
            fds_array[i] = 1;
            cli_addr = claddr[i];
            server_receive(srvrfd, recvbuf, 720, cli_addr);}
    }

    return 0;
}
客户机套接字地址取自3个客户机套接字的3元素数组claddr,创建套接字时,每个客户机套接字的相应位置都会被填充。在创建套接字时,我还调用FD_SET将客户机地址设置到FD_集中。我想我应该从fd_集合中获取客户机套接字地址,但是它们都是相同的指针值,所以我不知道为什么会有不同。对于internet域数据报套接字,我们可以使用getpeername,但我不知道UNIX域套接字是否有类似的功能,甚至不知道这是否是问题所在

非常感谢你在这方面的帮助

更新:

客户端FD在创建套接字时添加到全局fdset结构:

int64_t * create_socket_client(struct sockaddr_un claddr, int64_t retvals[])
{
    int sfd, j;
    size_t msgLen;
    ssize_t numBytes;
    char resp[BUF_SIZE];

    retvals[0] = 0;
    retvals[1] = 0;

    sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sfd == -1)
        return retvals;

    memset(&claddr, 0, sizeof(struct sockaddr_un));
    claddr.sun_family = AF_UNIX;
    snprintf(claddr.sun_path, sizeof(claddr.sun_path),  "/tmp/ud_ucase_cl.%ld", (long) getpid());

    FD_SET(sfd,&fdset);

    retvals[0] = sfd;
    retvals[1] = (int64_t)&claddr;

     return retvals;
}
代码清空fdset,然后只向fdset添加0。因此,当您调用select并将其传递给fdset时,您只要求它检查套接字0是否准备就绪

稍后检查fdset中是否存在小于fd_计数的0到1的套接字,但可能只有0,因为这是您唯一询问的套接字

要检查是否准备就绪的套接字列表在哪里

代码清空fdset,然后只向fdset添加0。因此,当您调用select并将其传递给fdset时,您只要求它检查套接字0是否准备就绪

稍后检查fdset中是否存在小于fd_计数的0到1的套接字,但可能只有0,因为这是您唯一询问的套接字


您要检查准备就绪的套接字列表在哪里?

当我看到模板示例时,我对为什么要清空fdset感到困惑,因为我已经填充了fdset。在本例中,客户端套接字FD的列表是5、6和7,正如Barmar在上面所示,我错误地发送了0、1和2,这是不正确的。也许你想制作一个全局fd_集的本地副本,而不是将fdset归零?Barmar说我应该制作一个本地副本,因为它是由select修改的-所以我会这样做。我很困惑,当我看到模板示例时为什么要清空fdset-我已经填充了fdset。在本例中,客户端套接字FD的列表是5、6和7,正如Barmar在上面所示,我错误地发送了0、1和2,这是不正确的。也许你想制作一个全局fd_集的本地副本,而不是将fd_集归零?Barmar说我应该制作一个本地副本,因为它是由select修改的,所以我会这样做。注释不用于扩展讨论;此对话已结束。是否在线程之间共享套接字描述符?select是否可能为您提供了一个描述符,可以读取到在同一套接字描述符上选择的两个不同线程2,但当第二个线程执行select时,另一个线程已被带到数据包中?注释不用于扩展讨论;此对话已结束。是否在线程之间共享套接字描述符?select是否可能为您提供了一个描述符,可以读取在同一套接字描述符上选择的两个不同线程,但当第二个线程执行select时,另一个线程已被数据包占用?
int64_t * create_socket_client(struct sockaddr_un claddr, int64_t retvals[])
{
    int sfd, j;
    size_t msgLen;
    ssize_t numBytes;
    char resp[BUF_SIZE];

    retvals[0] = 0;
    retvals[1] = 0;

    sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sfd == -1)
        return retvals;

    memset(&claddr, 0, sizeof(struct sockaddr_un));
    claddr.sun_family = AF_UNIX;
    snprintf(claddr.sun_path, sizeof(claddr.sun_path),  "/tmp/ud_ucase_cl.%ld", (long) getpid());

    FD_SET(sfd,&fdset);

    retvals[0] = sfd;
    retvals[1] = (int64_t)&claddr;

     return retvals;
}
FD_ZERO(&fdset);
FD_SET(0,&fdset);

socklen_t * len = (socklen_t * ) sizeof(struct sockaddr_un);

fds_ready = select(3, &fdset, NULL, NULL, 0);

for (int i = 0; i < fd_count; i++){
    fds_array[i] = 0;

    if (FD_ISSET(i, &fdset)) {