TCP服务器/客户端如何保持连接活着?

时间:2016-07-14 16:29:24

标签: c sockets tcp tcpserver

我写了一个简单的TCP echo服务器来处理多个客户端。它使用select()来获得多个连接。

服务器代码:

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>


int create_listener(uint16_t port) {

    int listen_fd;
    struct sockaddr_in name;

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd < 0) {
        perror ("socket");
        exit(EXIT_FAILURE);
    }

    bzero(&name, sizeof(name));
    name.sin_family = AF_INET;
    name.sin_addr.s_addr = htonl(INADDR_ANY);
    name.sin_port = htons(port);

    if (bind(listen_fd, (struct sockaddr *) &name, sizeof(name)) < 0) {
        perror ("bind");
        exit(EXIT_FAILURE);
    }


    return listen_fd;
}

int read_from_client(int fd) {
    char buffer[100];
    int nbytes;

    nbytes = read(fd, buffer, 100);
    if (nbytes < 0) {
        perror("read");
        exit(EXIT_FAILURE);
    }
    else if (nbytes == 0) {
        return -1;
    }
    else {
        fprintf(stderr, "Server: got message: %s\n", buffer);
        write(fd, buffer, strlen(buffer) + 1);
        return 0;
    }
}


int main(int argc, char *argv[]) {

    int listen_fd;
    uint16_t port = 22000;

    fd_set active_fd_set, read_fd_set;
    int i;

    struct sockaddr_in servaddr;

    /* Create the socket and set it up to accept connections. */
    listen_fd = create_listener(port);
    if (listen(listen_fd, 10) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    /* Initialize the set of active sockets. */
    FD_ZERO(&active_fd_set);
    FD_SET(listen_fd, &active_fd_set);


    while (1) {

        /* Block until input arrives on one or more active sockets. */
        read_fd_set = active_fd_set;
        if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, 0) < 0) {
            perror("select");
            exit(EXIT_FAILURE);
        }

        /* Service all the sockets with input pending. */
        for (i = 0; i < FD_SETSIZE; ++i) {
            if (FD_ISSET(i, &read_fd_set)) {
                if (i == listen_fd) {
                    /* Connection request on original socket. */
                    int new_fd;
                    new_fd = accept(listen_fd, (struct sockaddr *) NULL, NULL);

                    if (new_fd < 0) {
                        perror ("accept");
                        exit(EXIT_FAILURE);
                    }

                    FD_SET(new_fd, &active_fd_set);
                }
                else {
                    /* Data arriving on an already-connected socket. */
                    if (read_from_client(i) < 0) {
                        close(i);
                        FD_CLR(i, &active_fd_set);
                    }
                }
            }
        }
    }

    return 0;
}

客户代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {

    int sockfd, n;
    char sendline[100];
    char recvline[100];
    struct sockaddr_in servaddr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(22000);

    inet_pton(AF_INET, "127.0.0.1", &(servaddr.sin_addr));

    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));


    while (1) {
        bzero(sendline, 100);
        bzero(recvline, 100);
        fgets(sendline, 100, stdin);

        write(sockfd, sendline, strlen(sendline) + 1);
        read(sockfd, recvline, 100);

        printf("%s", recvline);
    }



    return 0;
}

问题是当我在一个终端中运行服务器并在另外两个终端中运行两个客户端时。如果我使用Ctrl + C终止一个客户端,服务器将自动终止。我想知道为什么服务器这样做。我期待的是服务器永远运行。当客户端1终止时,服务器仍应与客户端2建立实时连接。

1 个答案:

答案 0 :(得分:2)

您似乎正在点击exit中的read_from_client。通常,在为多个客户端提供服务的服务器中,当您遇到其中一个客户端连接失败时,您可能不想退出。