繁体   English   中英

AF_UNIX套接字:没有任何要读取的内容时会触发select()

[英]AF_UNIX socket: select() firing when there is nothing to read

该程序创建了n个线程来模拟分布式系统中的n个节点,每个线程都有一个侦听的套接字,并且每个线程可以通过connect调用与n-1个其他线程进行通信。

  1. 每个线程都会调用select()来查看是否有可用的东西,如果有的话,它接受并保存数据。

  2. 我将ioctl与FIONREAD标志一起使用,以检查可读取的字节数并进行适当的读取调用。 然后,关闭新的fd(来自accept())。

  3. 监听套接字正在阻塞。 未设置O_NONBLOCK。

  4. 所有n个线程运行相同的功能。 在函数中声明的所有变量都使用线程本地存储。

  5. 我没有进行任何明确的同步。 多个线程可以尝试一次连接到同一套接字。

现在,问题是,偶尔,接收方线程中的select()会记录一些新内容,但可用字节数为0,这是不应该的。 这不一致地发生。

如果有人可以指出我应该研究的地方,那就太好了。 谢谢!

制作袜子

  if ( (nptr->sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
                perror("socket");
                exit(1);
            }
            fd_max = nptr->sock > fd_max ? nptr->sock : fd_max;

            int ok=1;
            setsockopt(nptr->sock, SOL_SOCKET, SO_REUSEADDR, &ok, sizeof(int));

            nptr->addr.sun_family = AF_UNIX;
            snprintf(nptr->addr.sun_path, 20, "%d", nptr->id);
            //strncpy(nptr->addr.sun_path, sock_path, 20);

            if ( bind(nptr->sock, (struct sockaddr*)&(nptr->addr), sizeof(struct sockaddr_un)) < 0 ) {
                perror("bind");
                exit(1);
            }
            /* socket,  max connections */
            if ( listen(nptr->sock, 2*tot_node) < 0 ) {
                perror("listen");
                exit(1);
            }

寄东西

for (t=0; t<tot_node; t++) {
            ...

            if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                perror("socket");
                exit(1);
            }

            printf("Node %d: trying to req node %d... ", self->id, node_catalog[t]->id);
            if ( connect(fd, (struct sockaddr*)&(node_catalog[t]->addr), sizeof(struct sockaddr_un)) == -1 ) {
                perror("connect");
                exit(1);
            }

            buf[0] = TYPE_REQ;
            buf[1] = self->id;
            buf[2] = ts;
            buf[3] = rsc;

            write (fd, buf, 4*sizeof(int));

            //close(fd);

            printf("Node %d: sent req for resource %d to %d\n", self->id, rsc, node_catalog[t]->id);
        }
        usleep(TS_UPDATE_ITV);

接收东西

    FD_ZERO(&readset);
            FD_SET(self->sock, &readset);
            t = pselect(self->sock+1, &readset, NULL, NULL, &tout, NULL);
            if (t > 0 && FD_ISSET(self->sock, &readset)) {

                com_fd = accept(self->sock, NULL, NULL);

                ioctl(com_fd, FIONREAD, &t);
    #ifdef DEBUG
                printf("   Node %d: received %d bytes of data\n", self->id, t);
    #endif

                read(com_fd, buf, t);
                close(com_fd);

                dptr = (int *)buf;
                rsc = t / (sizeof(int)); /* var reuse. this is the count of ints to read */

                for (t=0; t<rsc; ) {
                    static __thread int nid, nts, nrsc;
    #ifdef DEBUG
                    printf("   Node %d: data rcvd: %d %d %d %d", self->id, *dptr, *(dptr+1), *(dptr+2), *(dptr+3));
    #endif

                   if (*dptr == TYPE_REQ) {
... } else {...}

您的代码没有意义。 select()被解雇的原因是有些东西要接受 在刚刚接受的套接字上检查FIONREAD可能会或可能不会导致数据可用。 这完全取决于客户端是否发送了任何内容。 不在select()的合同上。

如果需要知道是否有要读取的内容,则应将已接受的套接字添加到read-FD集中,并以循环方式进行处理:如果侦听套接字是可读的,则对其调用accept() ,否则为接受的套接字,则应在其上调用read()

在大多数情况下,检查FIONREAD实际上只是浪费时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM