传入连接如何停止选择等待

  • 本文关键字:选择 等待 何停止 连接 c
  • 更新时间 :
  • 英文 :


与示例中一样,select监视侦听传入连接的服务器的套接字。我用telnet测试程序。在程序中,select应该在listener套接字中有要读取的内容时停止等待。我猜telnet可能会向服务器发送一条消息,并试图读取它,但我一无所获。事实上,当我试图从telnet读取消息时,程序停止接受新连接。我注释掉了阅读代码的消息。有人能解释为什么在有新连接时select停止等待吗?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include "../cus_header/cus_header.h"
#define PORT "30000"  // the port users will be connecting to
#define MY_IP "127.0.0.1"
#define BACKLOG 10   // how many pending connections queue will hold
#define MAXLEN 1000
void *get_client_addr(struct sockaddr * sa){
    if(sa->sa_family == AF_INET){
        return &(((struct sockaddr_in *)(sa))->sin_addr);
    }
    return &(((struct sockaddr_in6 *)(sa))->sin6_addr);
}

int main(int argc, char *argv[]){
    struct addrinfo hints, *res, *p;
    struct sockaddr_storage client_addr;
    int client_add_len;
    char client_ip[INET6_ADDRSTRLEN];
    int a;
    int listener, new_fd;
    int yes = 1;
    socklen_t c_addr_size;
    char msg [] = "Hello clientn"; // message to the client
    char *msg_p;
    int msg_len = strlen(msg);

    // load data to struct addrinfo
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    //create socket
    if((a = getaddrinfo(MY_IP, PORT, &hints, &res)) == -1){
        fprintf(stderr, "Cannot get address info: %s", gai_strerror(a));
        return 1;
    }
    p = res;
    // loop through all the results
    for(p = res; p != NULL; p = p->ai_next){
        // create socket
        if((listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
            printf("cannot create the socketn");
            continue;
        }
        if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
            error("cannot set reused for the socket");
        }
        // bind socket to port
        if(bind(listener, p->ai_addr, p->ai_addrlen) == -1){
            printf("cannot bind the socketn");
            continue;
        }
        break;
    }
    if(p == NULL){
        error("Cannot create socket or bind the socket to the port");
    }
    freeaddrinfo(res);
    // listen incoming connections
    if(listen(listener, BACKLOG) == -1){
        error("Cannot listen to connection");
    }
    // ready to communicate
    puts("Waiting for connection ...");

    fd_set master_set, copy_master_set;
    int fd_max;
    int client_fd[20]; // store all the new fd here
    // accept connection and talk with clients

    while(1){
        FD_ZERO(&master_set);
        FD_SET(listener, &master_set);
        fd_max = listener;
        copy_master_set  = master_set;
        if(select(fd_max + 1, &copy_master_set, NULL, NULL, NULL) == -1){
            error("Select");
        }
        int i;
        // set all the available client fd
        for(i = 0;i <= fd_max; i++){
            if(FD_ISSET(i, &copy_master_set)){
                if(i == listener){
                    // got a new connection
                    client_add_len = sizeof client_addr;
                    if((new_fd = accept(listener, (struct sockaddr *)&client_addr, &client_add_len)) == -1){
                       error("New connection");
                    }
                    FD_SET(new_fd, &master_set);
                    if(new_fd > fd_max){
                        fd_max = new_fd;
                    }
                    printf("New connection from %s on socket %in",
                           inet_ntop(client_addr.ss_family, get_client_addr((struct sockaddr *)&client_addr), client_ip, INET6_ADDRSTRLEN),
                           new_fd);
                    /*
                    char buf[MAXLEN];
                    int b;
                    if((b=recv(listener, buf, MAXLEN, 0)) == -1){
                        error("read message");
                    }else if(b == 0){
                        printf("Message from client: %s", buf);
                    }
                    printf("Message from client: %s", buf);
                    */
                }else{
                // handle clients

                }
            }
        }

    }

    return 0;
}

从手册页选择:

说明select()和pselect()允许程序监视多个文件描述符,等待一个或多个文件描述符为某些类型的I/O操作(例如,输入可能)。如果文件描述符是pos,则认为它已准备好-能够执行相应的I/O操作(例如。,读取(2))而不阻塞。

在这种情况下,当套接字接收到传入连接时,文件描述符就准备好了,并且可以执行accept(2)的相应I/O操作。

最新更新