20

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...

4
  • Help me lords of SO.I am tired of trying Commented Dec 2, 2012 at 13:10
  • See stackoverflow.com/questions/27179/c-network-programming/… Commented Dec 2, 2012 at 13:11
  • @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. Commented Dec 2, 2012 at 13:14
  • 2
    "memset(&myaddr,'0',sizeof(myaddr));" is a funny typo :) Commented Dec 2, 2012 at 13:34

2 Answers 2

28

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;
        }
}
Sign up to request clarification or add additional context in comments.

6 Comments

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.
@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.
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.
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.
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.
|
3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.