Multiclient server using fork()

72,088

Solution 1

The main problem you have is that == has higher precedence than =, so this line:

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

is assigning the result of fork() == -1 to pid, which isn't what you want: it'll always be 0 when fork() succeeds, in both the child and the parent. You need to use:

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

You should also close(new) in the parent after the fork() - the child owns that socket now. If you want to send the textual version of the counter, you need to use snprintf() to convert it to text. The child should also exit after it's finished - the easiest way to do that in your code is to break out of the loop. After these corrections, the inner loop in your server looks like:

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;
        }
}

Solution 2

Try this one might you get solution,

Server Program:

#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);
}
}
}

Client Program:

#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);
}

Here code is doing communication for only one character.

Share:
72,088
user1724072
Author by

user1724072

Updated on July 09, 2022

Comments

  • user1724072
    user1724072 almost 2 years

    I am trying to create a socket programming server to handle multiple clients at the same time using fork().. But I am not able to implement it properly.I have been trying for a long time . The problems I am facing are 1) address bind problem 2) problem how to handle parent process and child process 3) how to end the server program ie ..return to the console My programs for a single client server were working properly.Here is my code for the multiple client-server.

    #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;
    }
    

    Here is the simple client program

        #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;
    }
    

    Can someone please tell me what I am doing wrong and what is the correct way to do it..? Any help will be greatly appreciated...

    • user1724072
      user1724072 over 11 years
      Help me lords of SO.I am tired of trying
    • Victor Sorokin
      Victor Sorokin over 11 years
    • user1724072
      user1724072 over 11 years
      @VictorSorokin:it would be great if you could look into my specific program or my purpose..I have already written that I had no problem with single client server.
    • loreb
      loreb over 11 years
      "memset(&myaddr,'0',sizeof(myaddr));" is a funny typo :)
  • NHDaly
    NHDaly about 11 years
    Can and/or should the child process close sockid as well? I ask, because I am running into the problem where I have a child process running in a loop, and later kill the parent and attempt to restart it, however it cannot bind the socket since the child process still has the server socket bound.
  • caf
    caf about 11 years
    @NHDaly: Yes, if the child is going to be long-lived. I didn't put that in the code here, because we knew the child was about to exit anyway.
  • NHDaly
    NHDaly about 11 years
    Okay, thanks. That's what I've been trying to do, but for some reason, once the child process exits, subsequent calls to accept(sockid,...) fail. I'm not very sure why.. perror tells me: failed to accept: Interrupted system call.
  • caf
    caf about 11 years
    NHDaly: That's just because the SIGCHLD sent to the parent when the child exited interrupted the accept(). EINTR should be considered a temporary failure - just loop around and retry the accept() in that case.
  • NHDaly
    NHDaly about 11 years
    ah, thanks. The problem was I was actually receiving two connections at the start of each loop, so I was always off by one when the first connection failed. Thank you.