C: «одинаковые файловые дескрипторы всех клиентских подключений» (программирование клиент-сервер) - PullRequest
2 голосов
/ 06 мая 2011

На каждом новом клиентском соединении разветвленный серверный процесс

разные процессы (другие дочерние элементы сервера, например, exec) не могли идентифицировать этого клиента с таким же fd, который используется в разветвленном дочернем элементе.

Как можноЯ различаю клиента на других процессах ??

принять вызов возвращает то же значение, если дескриптор файла новый sockfd

/* server process */ 
#include <ctype.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <signal.h> 
#define SIZE sizeof(struct sockaddr_in) 
void catcher(int sig); 
int newsockfd; 
int main(void) 
{ 
    int sockfd; 
    char c;
    struct sockaddr_in server = {AF_INET, 7000, INADDR_ANY}; 
    static struct sigaction act; 
    act.sa_handler = catcher; 
    sigfillset(&(act.sa_mask)); 
    sigaction(SIGPIPE, &act, NULL); 
    /* set up the transport end point */ 
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
        perror("socket call failed"); 
        exit(1); 
    } 
    /* bind an address to the end point */ 
    if ( bind(sockfd, (struct sockaddr *)&server, SIZE) == -1) 
    { 
        perror("bind call failed"); 
        exit(1); 
    }
    /* start listening for incoming connections */ 
    if ( listen(sockfd, 5) == -1 ) 
    { 
        perror("listen call failed"); 
        exit(1) ; 
    } 
    for (;;) 
    { 
        /* accept a connection */ 
        if ( (newsockfd = accept(sockfd, NULL, NULL)) == -1) 
        { 
            perror("accept call failed"); 
            continue; 
        } 
        printf("New connection. File descriptor fd is %d\n",newsockfd);
        /* spawn a child to deal with the connection */
        if ( fork() == 0) 
        { 
            while (recv(newsockfd, &c, 1, 0) > 0) 
            { 
                c = toupper(c); 
                send(newsockfd, &c,1, 0); 
            } 
            /* when client is no longer sending information the socket can be closed and the child process terminated */ 
            close(newsockfd); 
            exit (0); 
        } 
        /* parent doesn't need the newsockfd */ 
        close(newsockfd); 
    } 
} 
void catcher(int sig) 
{ 
    close(newsockfd); 
    exit (0); 
}












/* client process */ 
#include <ctype.h> 
#include <sys/types.h> 
#include<stdlib.h>
#include<stdio.h>
#include <sys/socket.h> 
#include <netinet/in.h> 
#define SIZE sizeof(struct sockaddr_in) 
int main(void) 
{ 
    int sockfd; 
    char c, rc; 
    struct sockaddr_in server = {AF_INET, 7000}; 
    /* convert and store the server's IP address */ 
    server.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    /* set up the transport end point */ 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
        perror("socket call failed"); 
        exit(1); 
    } 
    /* connect the socket to the server's address */ 
    if ( connect (sockfd, (struct sockaddr *)&server, SIZE) == -1) 
    { 
        perror("connect call failed"); 
        exit(1); 
    } 
    /* send and receive information with the server */ 
    for(rc = '\n';;) 
    { 
        if (rc == '\n') 
            printf("Input a lower case character\n"); 
        c = getchar(); 
        send(sockfd, &c, 1, 0); 
        if (recv(sockfd, &rc, 1, 0) >0) 
            printf("%c", rc);  
        else 
        {
            printf("server has died\n");
            close(sockfd);
            exit(1); 
        } 
    } 
} 

1 Ответ

3 голосов
/ 06 мая 2011

Номер дескриптора файла является уникальным только в рамках процесса, в котором он существует, и, как только он будет закрыт, его можно будет использовать повторно (например, при следующем вызове accept).Неправильный выбор «идентификатора соединения».

В вашем случае, когда у вас есть новый процесс для каждого соединения, наиболее естественным идентификатором соединения будет идентификатор процесса - но вы его выбросилине сохраняя возвращаемое значение fork.В родительском процессе fork возвращает pid дочернего процесса, который он создал.Вы хотите сохранить это и использовать позже.В частности, вы можете использовать его, чтобы убить дочерний процесс или определить, когда дочерний процесс завершится (wait -семейные функции сообщат вам, какой дочерний процесс вышел).

Конечно, если вся ваша модель будет использовать отдельныйпроцесс для каждого соединения, я не уверен, почему вам вообще нужно идентифицировать соединения в родительском процессе.Если каждое соединение не является полностью независимым процессом, вы могли бы намного лучше использовать потоки вместо процессов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...