web-dev-qa-db-fra.com

Serveur multiclient utilisant fork ()

J'essaie de créer un serveur de programmation de socket pour gérer plusieurs clients en même temps en utilisant fork () .. Mais je ne suis pas en mesure de l'implémenter correctement. J'essaye depuis longtemps. Les problèmes auxquels je suis confronté sont 1) le problème de liaison d'adresse 2) le problème de gestion du processus parent et du processus enfant 3) la fin du programme serveur, c'est-à-dire .. le retour à la console. mon code pour les multiples client-serveur.

#include<signal.h>
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<sys/types.h>
#include<stdlib.h>

int main()
{

    struct sockaddr_in myaddr ,clientaddr;
    int sockid,newsockid;
    sockid=socket(AF_INET,SOCK_STREAM,0);
    memset(&myaddr,'0',sizeof(myaddr));
    myaddr.sin_family=AF_INET;
    myaddr.sin_port=htons(8888);
    myaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
    if(sockid==-1)
    {
        perror("socket");
    }
    int len=sizeof(myaddr);
    if(bind(sockid,( struct sockaddr*)&myaddr,len)==-1)
    {
        perror("bind");
    }
    if(listen(sockid,10)==-1)
    {
        perror("listen");
    }
    int pid,new;
    static int counter=0;
    for(;;)
    {       a:
            new =accept(sockid,(struct sockaddr *)&clientaddr,&len);

            if(pid=fork()==-1)
            {
                close(new);
                continue;

            }   
            else if(pid>0)
            {
            counter++;
            //wait();
            goto a;
            printf("here2");
            //close(new);
            continue;
            }   
            else if(pid==0)
            {
            counter++;
            printf("here 1");
            send(new,"hi",100,0);
            send(new,(char *) &counter,1,0);

            //kill(pid,SIGKILL);
            //close(new);
            }

    }
    printf("here3");
    close(sockid);
    return 0;
}

Voici le programme client simple

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


int main()
{

    struct sockaddr_in myaddr ,serveraddr;
    int sockid;
    sockid=socket(AF_INET,SOCK_STREAM,0);
    memset(&myaddr,'0',sizeof(myaddr));
    myaddr.sin_family=AF_INET;
    myaddr.sin_port=htons(8888);
    myaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
    if(sockid==-1)
    {
        perror("socket");
    }
    int len=sizeof(myaddr);
    if(connect(sockid,(const struct sockaddr*)&myaddr,len)==-1)
    {
        perror("connect");
    }
    fprintf(stdout,"Client Online....");
    char s[10000];


        //gets(s);
        //send(sockid,s,10000,0);
        recv(sockid,&s,10000,0);
        fprintf(stdout,"Server says....");
        puts(s);
        recv(sockid,&s,10000,0);
        fprintf(stdout,"Server says....");
        puts(s);

sleep(10);  
    close(sockid);
    return 0;
}

Quelqu'un peut-il me dire ce que je fais mal et quelle est la bonne façon de le faire ..? Toute aide sera fortement appréciée...

14
user1724072

Le principal problème que vous avez est que == A une priorité plus élevée que =, Donc cette ligne:

if(pid=fork()==-1)

assigne le résultat de fork() == -1 à pid, ce qui n'est pas ce que vous voulez: ce sera toujours 0 lorsque fork() réussira, dans l'enfant et le parent. Vous devez utiliser:

if((pid = fork()) == -1)

Vous devez également close(new) dans le parent après fork() - l'enfant possède cette socket maintenant. Si vous souhaitez envoyer la version textuelle du compteur, vous devez utiliser snprintf() pour la convertir en texte. L'enfant doit également quitter après avoir terminé - la façon la plus simple de le faire dans votre code est de sortir de la boucle. Après ces corrections, la boucle interne de votre serveur ressemble à:

for(;;)
{
        new = accept(sockid, (struct sockaddr *)&clientaddr, &len);

        if ((pid = fork()) == -1)
        {
            close(new);
            continue;
        }
        else if(pid > 0)
        {
            close(new);
            counter++;
            printf("here2\n");
            continue;
        }
        else if(pid == 0)
        {
            char buf[100];

            counter++;
            printf("here 1\n");
            snprintf(buf, sizeof buf, "hi %d", counter);
            send(new, buf, strlen(buf), 0);
            close(new);
            break;
        }
}
19
caf

Essayez celui-ci si vous obtenez une solution,

Programme serveur:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>

int main()
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address,server_len);

/* Create a connection queue, ignore child exit details and wait for
clients. */

listen(server_sockfd, 5);

signal(SIGCHLD, SIG_IGN);

while(1) {
char ch;

printf("server waiting\n");

/* Accept connection. */

client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address, &client_len);

/* Fork to create a process for this client and perform a test to see
whether we're the parent or the child. */

if(fork() == 0) {

/* If we're the child, we can now read/write to the client on
client_sockfd.
The five second delay is just for this demonstration. */

read(client_sockfd, &ch, 1);
sleep(5);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
exit(0);
}

/* Otherwise, we must be the parent and our work for this client is
finished. */

else {
close(client_sockfd);
}
}
}

Programme client:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
void main()
{
    int sid;
    char s[10]={},s1[10]={};
    struct sockaddr_in ssock,csock;
    sid=socket(AF_INET,SOCK_STREAM,0);
    ssock.sin_family=AF_INET;
    ssock.sin_addr.s_addr=inet_addr("127.0.0.1");
    ssock.sin_port=htons(9734);
    connect(sid,(struct sockaddr *)&ssock,sizeof(ssock));
    while(1)
    {
        printf("\n Enter the string:");
        scanf("%s",s);
        write(sid,(void*)s,strlen(s));
        if(strlen(s)==0)
            break;
        sleep(1);
        read(sid,(void*)s1,sizeof(s1));
        printf("\n The received string is:%s\n",s1);
    }
    close(sid);
}

Ici, le code fait la communication pour un seul caractère.

2
ravi bhuva