2016-07-14 15 views
0

여러 개의 클라이언트를 처리하기 위해 간단한 TCP 에코 서버를 작성했습니다. select()를 사용하여 여러 연결을 가져옵니다.TCP 서버/클라이언트 연결을 유지하는 방법은 무엇입니까?

서버 코드 :

#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와 실시간으로 연결되어 있어야합니다.

+0

'read_from_client'에서'exit'를 치고 싶습니까? –

+0

@Andy Schweig 당신은 그것을 가지고 있습니다. 대답 해 주시면 답변 해 드리겠습니다. – Luke

답변

2

exitread_from_client에있는 것처럼 보입니다. 일반적으로 여러 클라이언트에 서비스를 제공하는 서버에서는 클라이언트 연결 중 하나에서 오류가 발생하면 종료하지 않으려 고합니다.

관련 문제