select()或send()有时会失败吗?

时间:2013-07-01 13:33:15

标签: c sockets select

我遇到AF_INET套接字问题。

我有两个通过套接字进行通信的进程。我正在使用send()recv()select()

有时,当我将第一条消息从一方发送到另一方时,它会卡住,就像select()从未意识到消息......或者它永远不会到达那里,我不会知道。

起初,我检查了我的代码调试它,我发现当我这样做时,它永远不会失败。它似乎在我在控制台上执行时失败(有时)。

有什么想法吗?

编辑 - 2.我将几乎所有的代码。

这是主要代码

void main() {
    t_list *levelsList = getLevelsList();
    char *levelName = (char *) malloc(MAXSIZE);
    t_level_address *addresses = (t_level_address *) malloc(sizeof(t_level_address));
    t_dictionary *levelsMap = dictionary_create();

    levelsMap = getLevelsMap();

    char** port = (char*) malloc(MAXSIZE);
    int i;
    t_dictionary *levels_queues = dictionary_create();

    for (i = 0; i < list_size(levelsList); i++) {
        pthread_t *t = (pthread_t*) malloc(sizeof(pthread_t));
        levelName = (char *) list_get(levelsList, i);
        addresses = (t_level_address*) dictionary_get(levelsMap, levelName);
        port = string_split(addresses->planificador, DOSPUNTOS);
        t_scheduler_queue *scheduler_queue = (t_scheduler_queue*) malloc(sizeof(t_scheduler_queue));
        scheduler_queue->blocked_queue = queue_create();
        scheduler_queue->character_queue = queue_create();
        scheduler_queue->port = port[1];
        dictionary_put(levels_queues, levelName, scheduler_queue);
        pthread_create(t, NULL, (void *) planificador, (t_scheduler_queue*) scheduler_queue);
    }

    free(levelName);
    free(addresses);
    free(levelsList);

    int sock; /* fd del listener*/
    int connectlist[MAXQUEUE]; /* array de sockets conectados */
    fd_set socks; /* lista de fds */
    int highsock; /* Highest #'d file descriptor, needed for select() */

    int readsocks; /* Number of sockets ready for reading */

    /* Obtain a file descriptor for our "listening" socket */
    sock = socketServer(PORT);
    listen(sock, MAXQUEUE);
    highsock = sock;
    memset((char *) &connectlist, 0, sizeof(connectlist));

    while (1) {
        build_select_list(sock, connectlist, highsock, &socks);
        readsocks = select(FD_SETSIZE, &socks, (fd_set *) 0, (fd_set *) 0, NULL);
        if (readsocks < 0) {
            perror("select");
            exit(1);
        } else
            accionar(sock, connectlist, highsock, socks, levelsMap, levels_queues);
    }
}


void accionar(int sock, int connectlist[], int highsock, fd_set socks, t_dictionary *levelsMap, t_dictionary *levels_queues) {
    int listnum;

    // Devuelvo el valor correspondiente al fd listener para primero gestionar conexiones nuevas.
    if (FD_ISSET(sock,&socks)){
        orquestador(levelsMap, handle_new_connection(sock, connectlist, highsock, socks), levels_queues);
    }
    for (listnum = 0; listnum < MAXQUEUE; listnum++) {
        if (FD_ISSET(connectlist[listnum],&socks))
            orquestador(levelsMap, connectlist[listnum], levels_queues);
    }
}

void orquestador(t_dictionary *levelsMap, int *fd, t_dictionary *levels_queues) {
    char *response = (char *) malloc(MAXSIZE); //CHECK LENGTH
    printf("Realizo el pop\n");
    response = recieveMessage(fd);
    if(!string_starts_with(response, BROKEN)){
        executeResponse(response, levelsMap, fd, levels_queues);
    }
}

这是我制作的图书馆。

void setnonblocking(int sock) {
    int opts;

    opts = fcntl(sock, F_GETFL);
    if (opts < 0) {
        perror("fcntl(F_GETFL)");
        exit(1);
    }
    opts = (opts | O_NONBLOCK);
    if (fcntl(sock, F_SETFL, opts) < 0) {
        perror("fcntl(F_SETFL)");
        exit(1);
    }
    return;
}

void build_select_list(int sock, int connectlist[], int highsock, fd_set *socks) {
    int listnum; /* Current item in connectlist for for loops */

    /* First put together fd_set for select(), which will
    consist of the sock veriable in case a new connection
    is coming in, plus all the sockets we have already
    accepted. */

    /* FD_ZERO() clears out the fd_set called socks, so that
    it doesn't contain any file descriptors. */

    FD_ZERO(socks);

    /* FD_SET() adds the file descriptor "sock" to the fd_set,
    so that select() will return if a connection comes in
    on that socket (which means you have to do accept(), etc. */

    FD_SET(sock, socks);

    /* Loops through all the possible connections and adds
    those sockets to the fd_set */

    for (listnum = 0; listnum < MAXQUEUE; listnum++) {
        if (connectlist[listnum] != 0) {
            FD_SET(connectlist[listnum], socks);
            if (connectlist[listnum] > highsock)
                highsock = connectlist[listnum];
        }
    }
}

int *handle_new_connection(int sock, int connectlist[], int highsock, fd_set socks) {
    int listnum; /* Current item in connectlist for for loops */
    int *connection = (int*) malloc(sizeof(int)); /* Socket file descriptor for incoming connections */
    int finish = 0;

    /* We have a new connection coming in! We'll
    try to find a spot for it in connectlist. */
    connection = accept(sock, NULL, NULL );
    if (connection < 0) {
        perror("accept");
        exit(1);
    }
    setnonblocking(connection);
    for (listnum = 0; (listnum < MAXQUEUE) && (finish != 0); listnum++)
        if (connectlist[listnum] == 0) {
            printf("\nConnection accepted: FD=%d; Slot=%d\n", connection, listnum);
            connectlist[listnum] = connection;
            finish = 1;
        }
    return connection;
}

int *handle_new_connection_scheduler(int sock, int connectlist[], int highsock, fd_set socks) {
    int listnum; /* Current item in connectlist for for loops */
    int *connection = (int*) malloc(sizeof(int)); /* Socket file descriptor for incoming connections */
    int finish = 0;

    /* We have a new connection coming in! We'll
    try to find a spot for it in connectlist. */
    connection = accept(sock, NULL, NULL );
    if (connection < 0) {
        perror("accept");
        exit(1);
    }
    setnonblocking(connection);
    return connection;
}

void deal_with_data(int listnum, int connectlist[MAXQUEUE]) {
    char *buffer = (char*) malloc(MAXSIZE); /* Buffer for socket reads */
    int fd = connectlist[listnum];
    buffer = recieveMessage(fd);
    if (string_starts_with(buffer, BROKEN)) {
        /* Connection closed, close this end
        and free up entry in connectlist */
        printf("\nConnection lost: FD=%d; Slot=%d\n", connectlist[listnum], listnum);
        close(connectlist[listnum]);
        connectlist[listnum] = 0;
    } else {
        /**
        * HAGO ALGO
        */
    }
}

void read_socks(int sock, int connectlist[], int highsock, fd_set socks) {
    int listnum;

    // Devuelvo el valor correspondiente al fd listener para primero gestionar conexiones nuevas.
    if (FD_ISSET(sock,&socks))
        handle_new_connection(sock, connectlist, highsock, socks);

    for (listnum = 0; listnum < MAXQUEUE; listnum++) {
        if (FD_ISSET(connectlist[listnum],&socks))
            deal_with_data(listnum, connectlist);
    }
}

int selecting() {
    int sock; /* fd del listener*/
    int connectlist[MAXQUEUE]; /* array de sockets conectados */
    fd_set socks; /* lista de fds */
    int highsock; /* Highest #'d file descriptor, needed for select() */

    int port; /* The port number after conversion from ascport */
    struct sockaddr_in server_address; /* bind info structure */
    int reuse_addr = 1; /* Used so we can re-bind to our port
                           while a previous connection is still
                           in TIME_WAIT state. */
    int readsocks; /* Number of sockets ready for reading */

    /* Obtain a file descriptor for our "listening" socket */
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        exit(1);
    }
    /* So that we can re-bind to it without TIME_WAIT problems */
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));

    /* Set socket to non-blocking with our setnonblocking routine */
    setnonblocking(sock);

    /* Get the address information, and bind it to the socket */
    port = atoi(port); /* le paso el puerto */
    memset((char *) &server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY );
    server_address.sin_port = port;
    if (bind(sock, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
        perror("bind");
        close(sock);
        exit(1);
    }

    /* Set up queue for incoming connections. */
    listen(sock, MAXQUEUE);

    highsock = sock;
    memset((char *) &connectlist, 0, sizeof(connectlist));

    while (1) { /* Main server loop - forever */
        build_select_list(sock, connectlist, highsock, &socks);
        readsocks = select(FD_SETSIZE, &socks, (fd_set *) 0, (fd_set *) 0, NULL);
        if (readsocks < 0) {
            perror("select");
            exit(1);
        }
        if (readsocks == 0) {
            /* Nothing ready to read, just show that we're alive */
            printf(".");
            fflush(stdout);
        } else
            read_socks(sock, connectlist, highsock, socks);
    }
}

0 个答案:

没有答案