Why does my server cannot respond to multiple clients simultaneously even after using fork function?
by intstudent123 from LinuxQuestions.org on (#4Y82H)
Hi, I'm a newbie here. I'm trying to create an SMTP server that can respond to multiple clients simultaneously. I use the fork function in socket programming. Below is the server program (not including the variables).
smtp.c
Code: ...
system("clear");
// create socket
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == ERR){
perror("socket: ");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(SMTP);
server.sin_addr.s_addr = INADDR_ANY;
// bind
len = sizeof(struct sockaddr_in);
if(bind(sock, (struct sockaddr *)&server, sizeof(server)) == ERR){
perror("bind");
exit(-1);
}
// listen
if((listen(sock, 10)) == ERR){
perror("listen");
exit(-1);
}
while(1){
memset(buff, 0, sizeof(buff));
memset(msg, 0, sizeof(msg));
memset(to, 0, sizeof(to));
memset(Cc, 0, sizeof(Cc));
printf("(SMTP) Waiting for connection\n");
if((cli = accept(sock, (struct sockaddr *)&client, &len)) == ERR){
perror("accept");
exit(-1);
}
// create child process
child_pid = fork();
if (child_pid < 0) {
perror("fork");
exit(-1);
}
// child
else if (child_pid == 0) {
close(sock); // close child copy
// receive from client
recv(cli, to, sizeof(msg), 0);
printf("Connection request to %s\n",to);
for(k=0;;k++){
sprintf(file_dir,"%s/mail%d.txt", to, k+1);
if ((fp = fopen(file_dir, "r")) == NULL) break;
}
fp = fopen(file_dir, "w");
while(strcmp(msg,".") != 0){
recv(cli, msg, sizeof(msg),0);
if(strcmp(msg,".") == 0){
strcpy(buff, "1");
}
else{
strcpy(buff, "0");
}
fprintf(fp, "%s\n", msg);
send(cli, buff, sizeof(buff), 0);
}
fclose(fp);
// Cc
// init buff and msg
memset(buff, 0, sizeof(buff));
memset(msg, 0, sizeof(msg));
// process
recv(cli, Cc, sizeof(msg), 0);
printf("Connection request to %s\n\n",Cc);
for(k=0;;k++){
sprintf(file_dir,"%s/mail%d.txt", Cc, k+1);
if ((fp = fopen(file_dir, "r")) == NULL) break;
}
fp = fopen(file_dir, "w");
while(strcmp(msg,".") != 0){
recv(cli, msg, sizeof(msg),0);
if(strcmp(msg,".") == 0){
strcpy(buff, "1");
}
else{
strcpy(buff, "0");
}
fprintf(fp, "%s\n", msg);
send(cli, buff, sizeof(buff), 0);
}
fclose(fp);
close(cli);
exit(0); // child exits here
}
// parent
else{
close(cli); // close parent copy
waitpid(child_pid, NULL, 0); // waits for child to exit
}
}
close(sock);
return 0;
...To test it, I open two terminals, for example, A and B. At A's terminal, I write emails to C and B. At the same time, I write emails at B's terminal to A and C. After entering '.' at A's terminal to send the emails, I tried to send B's emails without exiting from A's terminal.
The result turns out like this:
Quote:
But I want the result to be like this:
Quote:
Are there any mistakes in the flow of the coding? It would be great if there's anyone that can help so that I can improve my understanding of socket and fork. Thank you in advance.


smtp.c
Code: ...
system("clear");
// create socket
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == ERR){
perror("socket: ");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(SMTP);
server.sin_addr.s_addr = INADDR_ANY;
// bind
len = sizeof(struct sockaddr_in);
if(bind(sock, (struct sockaddr *)&server, sizeof(server)) == ERR){
perror("bind");
exit(-1);
}
// listen
if((listen(sock, 10)) == ERR){
perror("listen");
exit(-1);
}
while(1){
memset(buff, 0, sizeof(buff));
memset(msg, 0, sizeof(msg));
memset(to, 0, sizeof(to));
memset(Cc, 0, sizeof(Cc));
printf("(SMTP) Waiting for connection\n");
if((cli = accept(sock, (struct sockaddr *)&client, &len)) == ERR){
perror("accept");
exit(-1);
}
// create child process
child_pid = fork();
if (child_pid < 0) {
perror("fork");
exit(-1);
}
// child
else if (child_pid == 0) {
close(sock); // close child copy
// receive from client
recv(cli, to, sizeof(msg), 0);
printf("Connection request to %s\n",to);
for(k=0;;k++){
sprintf(file_dir,"%s/mail%d.txt", to, k+1);
if ((fp = fopen(file_dir, "r")) == NULL) break;
}
fp = fopen(file_dir, "w");
while(strcmp(msg,".") != 0){
recv(cli, msg, sizeof(msg),0);
if(strcmp(msg,".") == 0){
strcpy(buff, "1");
}
else{
strcpy(buff, "0");
}
fprintf(fp, "%s\n", msg);
send(cli, buff, sizeof(buff), 0);
}
fclose(fp);
// Cc
// init buff and msg
memset(buff, 0, sizeof(buff));
memset(msg, 0, sizeof(msg));
// process
recv(cli, Cc, sizeof(msg), 0);
printf("Connection request to %s\n\n",Cc);
for(k=0;;k++){
sprintf(file_dir,"%s/mail%d.txt", Cc, k+1);
if ((fp = fopen(file_dir, "r")) == NULL) break;
}
fp = fopen(file_dir, "w");
while(strcmp(msg,".") != 0){
recv(cli, msg, sizeof(msg),0);
if(strcmp(msg,".") == 0){
strcpy(buff, "1");
}
else{
strcpy(buff, "0");
}
fprintf(fp, "%s\n", msg);
send(cli, buff, sizeof(buff), 0);
}
fclose(fp);
close(cli);
exit(0); // child exits here
}
// parent
else{
close(cli); // close parent copy
waitpid(child_pid, NULL, 0); // waits for child to exit
}
}
close(sock);
return 0;
...To test it, I open two terminals, for example, A and B. At A's terminal, I write emails to C and B. At the same time, I write emails at B's terminal to A and C. After entering '.' at A's terminal to send the emails, I tried to send B's emails without exiting from A's terminal.
The result turns out like this:
Quote:
| (SMTP)Waiting for connection Connection request to C Connection request to B (SMTP)Waiting for connection Connection request to (SMTP)Waiting for connection |
Quote:
| (SMTP) Waiting for connection Connection request to C Connection request to B (SMTP) Waiting for connection Connection request to A Connection request to C (SMTP) Waiting for connection |