Multiclient server using fork()
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.
user1724072
Updated on July 09, 2022Comments
-
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 over 11 yearsHelp me lords of SO.I am tired of trying
-
Victor Sorokin over 11 years
-
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 over 11 years"memset(&myaddr,'0',sizeof(myaddr));" is a funny typo :)
-
-
NHDaly about 11 yearsCan 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 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 about 11 yearsOkay, 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 about 11 yearsNHDaly: That's just because the
SIGCHLD
sent to the parent when the child exited interrupted theaccept()
.EINTR
should be considered a temporary failure - just loop around and retry theaccept()
in that case. -
NHDaly about 11 yearsah, 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.