C 套接字 - 在选择时被阻止

标签 c sockets select-function

我正在开发一个客户端服务器程序,它使用 select() 调用来监听多个套接字。但是我的 select 调用被阻止了,尽管我在其中一个套接字中收到了一条消息,但 select() 调用无法识别它并且它仍在无限期地等待。

程序中有 2 个实体,一个 master 和一个 client。 master 知道它将处理的客户端数量并等待客户端连接到它。一旦收到客户确认,它就会存储其信息。一旦所有客户端都连接起来,它就会将其相邻客户端的信息发送给每个客户端,这样它就可以形成一个网络。就在这里,我使用 select() 来监视许多套接字, 主人有一个 socket ,每个 child 都连接到它 客户端有 3 个主 socket s1-与主人交谈 s2-child 在此套接字上监听连接 邻居-邻居等待连接的套接字。(即邻居中的 S2) p- 作为其邻居连接结果的套接字(接受 s2 - 返回 ths) 我使用 select 来监听服务器,它自己的套接字用于传入连接和一次。

最初,我的服务器向其中一个客户端发送一个字符串“hello”,该客户端接收此消息并将其传递给邻居,这样当字符串返回到已从服务器收到此消息的第一个 child 时,它把它传递给它的邻居。但是尽管所有 child 都在 select() 中等待输入。是什么原因导致的??

void main(int argc, char **argv) {

    int s1, s2, n, server_port, sc1, sc2, rv, rc, left_peer_port;
    int peer_port;
    fd_set writefds, readfds;
    struct timeval tv;
    struct hostent *server_info, *child_info, *left_peer_info;
    int start_flag = 0;

    struct sockaddr_in server, peer, incoming;

    char host_child[64];
    char *left_host = malloc(1);
    char *right_host = malloc(1);
    char buf1[256];
    char buf2[256];

    server_port = atoi(argv[2]);

    //speak to peer using this
    s2 = socket(AF_INET, SOCK_STREAM, 0);
    if (s2 < 0) {
        perror("socket:");
        exit(s2);
    }

    peer_port = server_port + 1;

    gethostname(host_child, sizeof host_child);

    child_info = gethostbyname(host_child);

    if (child_info == NULL) {
        fprintf(stderr, "%s: host not found (%s)\n", argv[0], host_child);
        exit(1);
    }


    peer.sin_family = AF_INET;
    memcpy(&peer.sin_addr, child_info->h_addr_list[0], child_info->h_length);
    int changeport = 0;
    do {
        peer.sin_port = htons(peer_port);
        rc = bind(s2, (struct sockaddr *) &peer, sizeof(peer));

        if (rc < 0) {
            //perror("bind:");
            peer_port++;
            changeport = 1;
            //exit(rc);

        } else {
            changeport = 0;
        }

    } while (changeport == 1);

    if (listen(s2, 100) == -1) {
        perror("listen");
        exit(3);
    }



//Now talk to server

    server_info = gethostbyname(argv[1]);

    if (server_info == NULL) {
        fprintf(stderr, "%s: host not found\n", argv[0]);
        exit(1);
    }


// pretend we've connected both to a server at this point
//speak to server using this
    s1 = socket(AF_INET, SOCK_STREAM, 0);
    if (s1 < 0) {
        perror("socket:");
        exit(s1);
    }


    server.sin_family = AF_INET;
    server.sin_port = htons(server_port);
    memcpy(&server.sin_addr, server_info->h_addr_list[0], server_info->h_length);

//To talk to the server

    sc1 = connect(s1, (struct sockaddr *) &server, sizeof(server));
    if (sc1 < 0) {
        perror("connect:");
        exit(sc1);
    }

    int send_len;
    char *str = malloc(1);
    sprintf(str, "%d", peer_port);
    printf("\nport-here=%s\n", str);


    send_len = send(s1, str, strlen(str), 0);
    if (send_len != strlen(str)) {
        perror("send");
        exit(1);
    }

    int recv_len;
    char buf[100];
    int ref = 0;
    int recv_stage = 0;
    int start_id;


    recv_len = recv(s1, buf, 34, 0);
    if (recv_len < 0) {
        perror("recv");
        exit(1);
    }
    buf[recv_len] = '\0';
    char *temp_port;

    if (!strcmp("close", buf))
        printf("%s", buf);
            //break;
    else {
        char *temp_buffer = malloc(1);
        char *id = malloc(100);
        char *pp = malloc(1);
        strcpy(temp_buffer, buf);

        char *search = ":";
        temp_port = strtok(temp_buffer, search);
        strcpy(buf, temp_port);
        printf("temp_name%s", temp_port);

        temp_port = strtok(NULL, search);
        strcpy(pp, temp_port);
        printf("temp_port%s", temp_port);
        temp_port = strtok(NULL, search);
        strcpy(id, temp_port);
        printf("id%s", temp_port);

        strcpy(temp_port, pp);
        printf("\nbuf=%s\n", buf);
        printf("\nport=%s\n", temp_port);
        printf("\nid=%s\n", id);
        start_id = atoi(id);
    }

//To send packet to its neighbour
    left_peer_info = gethostbyname(buf);
    printf("\nleft host=%s\n", buf);
    if (left_peer_info == NULL) {
        fprintf(stderr, "%s: host not found\n", left_host);
        exit(1);
    }
    left_peer_port = atoi(temp_port);


    int neighbour_socket;
    struct hostent *neighbour_info;
    struct sockaddr_in neighbour;
    neighbour_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (neighbour_socket < 0) {
        perror("socket:");
        exit(neighbour_socket);
    }

    neighbour_info = left_peer_info;


    neighbour.sin_family = AF_INET;
    neighbour.sin_port = htons(left_peer_port);
    memcpy(&neighbour.sin_addr, neighbour_info->h_addr_list[0], neighbour_info->h_length);

    printf("\nconnected to port %d\n", left_peer_port);
    //To talk to the neighbour
    printf("\ncomes here\n");


//Listen on this socket connection for potato

    int send_peer_len;
    int nfds;

    nfds = MAX(MAX(neighbour_socket, s2), s1);

// clear the set ahead of time
    FD_ZERO(&writefds);

// add our descriptors to the set
    FD_SET(neighbour_socket, &writefds);
    FD_SET(s1, &writefds);
    FD_SET(s2, &writefds);

//FD_SET(s2, &writefds);


    FD_ZERO(&readfds);
    FD_SET(neighbour_socket, &readfds);
    FD_SET(s1, &readfds);
    FD_SET(s2, &readfds);

//select()

// since we got s2 second, it's the "greater", so we use that for
// the n param in select()
//n = s1 + 1;

// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
    tv.tv_sec = 10;
    tv.tv_usec = 500000;

    int fds[3];
    fds[0] = s1;
    fds[1] = s2;
    fds[2] = neighbour_socket;
    int p = 0;
    int p_flag = 0;

    while (1) {
        printf("\n nfds = %d , p = %d \n", nfds, p);
        char buf_msg[64];


        //This is where the error occurs  //

        rv = select(nfds, &readfds, NULL, NULL, 0);

        //This is where the error occurs  //

        if (rv == -1) {
            perror("select"); // error occurred in select()
        } else if (rv == 0) {
            printf("Timeout occurred!  No data after 10.5 seconds.\n");
        } else {
            // one or both of the descriptors have data
            //reading message from server
            int select_fd;
            for (select_fd = 0; select_fd <= nfds; select_fd++) {

                if (FD_ISSET(select_fd, &readfds) != 0) {
                    if (select_fd == s1) {

                        recv_len = 0;
                        recv_len = recv(s1, buf_msg, 34, 0);
                        if (recv_len < 0) {
                            perror("recv");
                            exit(1);
                        }
                        buf_msg[recv_len] = '\0';
                        printf("\nreceived from server = %s\n", buf_msg);
                        //send to neighbour

                        int sc3;
                        sc3 = connect(neighbour_socket, (struct sockaddr *) &neighbour, sizeof(neighbour));
                        if (sc3 < 0) {
                            perror("connect:");
                            exit(sc3);

                        }

                        str = malloc(1);
                        strcpy(str, buf_msg);
                        send_len = send(neighbour_socket, str, strlen(str), 0);
                        printf("\n send - len - s1  - %d\n", send_len);
                        if (send_len != strlen(str)) {
                            perror("send");
                            exit(1);
                        }
                        start_flag = 1;
                        //FD_CLR(s1, &readfds);

                        printf("\ncrossed server\n");

                    } else if (select_fd == s2) {

                        int list_len = sizeof incoming;
                        printf("\ninside client\n");
                        printf("\nWaiting for accept in S2\n");
                        if (p_flag == 0) {
                            p_flag = 1;
                            p = accept(s2, (struct sockaddr *) &incoming, &list_len);
                            printf("\nConnection accepted in S2\n");
                            if (p < 0) {
                                perror("bind:");
                                exit(rc);
                            }
                        }
                        nfds = MAX(nfds, p);
                        recv_len = 0;
                        buf_msg[recv_len] = '\0';
                        recv_len = recv(p, buf_msg, 34, 0);
                        if (recv_len < 0) {
                            perror("recv");
                            exit(1);
                        }
                        buf_msg[recv_len] = '\0';
                        printf("\nreceived from client = %s\n", buf_msg);
                        //send to neighbour

                        //if(start_id!=1){
                        int sc3;
                        sc3 = connect(neighbour_socket, (struct sockaddr *) &neighbour, sizeof(neighbour));
                        if (sc3 < 0) {
                            perror("connect:");
                            //exit(sc3);
                        }
                        //}

                        str = malloc(1);
                        strcpy(str, buf_msg);
                        send_len = send(neighbour_socket, str, strlen(str), 0);
                        printf("\n send - len - s2  - %d\n", send_len);
                        if (send_len != strlen(str)) {
                            perror("send");
                            exit(1);
                        }

                    } else if (select_fd == neighbour_socket) {

                        printf("\ncomes in\n");

                    } else if (select_fd == p && p != 0) {

                        int list_len = sizeof incoming;
                        printf("\ninside p\n");
                        recv_len = 0;
                        buf_msg[recv_len] = '\0';
                        printf("\nwaiting at recv in P\n");

                        recv_len = recv(p, buf_msg, 34, 0);

                        printf("\ncrossed at recv in P\n");
                        if (recv_len < 0) {
                            perror("recv");
                            exit(1);
                        }
                        buf_msg[recv_len] = '\0';
                        printf("\nreceived from client = %s\n", buf_msg);
                        //send to neighbour
                        str = malloc(1);
                        strcpy(str, buf_msg);
                        send_len = send(neighbour_socket, str, strlen(str), 0);
                        printf("\n send - len - neighbour - %d\n", send_len);
                        if (send_len != strlen(str)) {
                            perror("send");
                            exit(1);
                        }
                    }
                }
            }

            FD_ZERO(&readfds);
            //FD_SET(neighbour_socket,&readfds);
            FD_SET(s1, &readfds);
            FD_SET(neighbour_socket, &readfds);

            if (p_flag == 1) {
                printf("\nsetting P\n");
                FD_SET(p, &readfds);
                FD_SET(s2, &readfds);

                p_flag = 0;
            } else {
                printf("\nNot setting P\n");
                FD_SET(s2, &readfds);
            }
        }
    }
    close(s1);
    close(s2);
} 

提前致谢。

最佳答案

select 的第一个参数必须是最大文件描述符加上一个。据我所知,在你发布的那一大堆代码中,你忘记了“加一”。

关于C 套接字 - 在选择时被阻止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7857990/

相关文章:

python - 复数和分形

c - 为什么我的C程序生成的机器代码与书中给出的不同?

C - 将文件内容写入缓冲区

c - Linux 信号带有额外的信息参数

网络崩溃和套接字的后续状态

c - select() 未检测到传入数据

c - 为什么我会在这个 C 程序中得到这个运行时错误?请告诉我哪里出了问题

c - 如何在内存中顺序存储可变长度代码?

C raw sockets 数据包看起来不错但没有逃脱网络

Node.js - Socket.io - 问题 "maximum concurrent connections"