1

I want to Create a mail server. The server connects two clients at a time. When two clients are connected, each client can alternatively enter a text and read text written by the other client. The server will display in both clients the following messages:

client 1 said : .......
what is your answer?
.....
....

I am trying for days to figure out how to make connection between two clients all I can do is to communicate between the server and the client (sending and receiving texts) but i have no idea how to connect with the other client through the server (i have to use FORK() in this task). any help will be greatly appreciated

here the code of the server :

#include  "unistd.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "netdb.h"

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "strings.h"
#include "sys/wait.h"


    //Function Prototypes
    void myabort(char *);

    //Some Global Variables
    int serverport = 3000;
    char * eptr = NULL;
    int listen_socket, client_socket;
    struct sockaddr_in Server_Address, Client_Address;
    int result,i;
    socklen_t csize;
    pid_t processid;
    int childcount = 0;


    //main()
    int
    main(int argc, char **argv){

    char buf[100];
    char tmp[100];
          char * ptr;
         int n, sent, length;

        //Step 0: Process Command Line
         if (argc > 2){
             myabort("Usage: server ");
         }
        if (argc == 2){
             serverport =  (int) strtol(argv[1], &eptr, 10);
               if (*eptr != '\0') myabort("Invalid Port Number!");
          }

    //Step 1: Create a socket
          listen_socket = socket(PF_INET, SOCK_STREAM, 0);
          if (listen_socket == -1) myabort("socket()");


      //Step 2: Setup Address structure
         bzero(&Server_Address, sizeof(Server_Address));
          Server_Address.sin_family = AF_INET;
          Server_Address.sin_port = htons(serverport);
          Server_Address.sin_addr.s_addr = INADDR_ANY;


     //Step 3: Bind the socket to the port
          result = bind(listen_socket, (struct sockaddr *) &Server_Address, sizeof(Server_Address));
          if (result == -1) myabort("bind()");

    //Step 4:Listen to the socket
          result = listen(listen_socket, 1);
         if (result == -1) myabort("listen()");



    printf("\nThe forkserver :%d\n",ntohs(Server_Address.sin_port));
        fflush(stdout);
     //Step 5: Setup an infinite loop to make connections
        while(1){


    //Accept a Connection
             csize = sizeof(Client_Address);
               client_socket = accept( listen_socket,(struct sockaddr *) &Client_Address,&csize);
            if (client_socket == -1) myabort("accept()");

              printf( "\nClient Accepted!\n" );


            //fork this process into a child and parent
              processid = fork();

               //Check the return value given by fork(), if negative then error,
              //if 0 then it is the child.
              if ( processid == -1){
                  myabort("fork()");
            }else if (processid == 0){
                  /*Child Process*/

                close(listen_socket);
                  //loop until client closes
                 while (1){



                    //read string from client
                    bzero(&buf, sizeof(buf));
                    do{
                        bzero(&tmp, sizeof(tmp));
                        n = read(client_socket,(char *) &tmp, 100);
                        //cout << "server:  " << tmp;
                        tmp[n] = '\0';
                        if (n == -1) myabort("read()");
                        if (n == 0) break;
                        strncat(buf, tmp, n-1);
                        buf[n-1] = ' ';
                    } while (tmp[n-1] != '\n');

                    buf[ strlen(buf) ] = '\n';

                printf( "From client: %s",buf);

                    if (n == 0) break;


                     //write string back to client
                    sent = 0;
                    ptr = buf;
                      length = strlen(buf);

                    //the vowels in the message are converted into upper case.
                    for( i = 0; ptr[ i ]; i++)
                    {
                        if( ptr[i]=='a' ||  ptr[i]=='e' ||  ptr[i]=='i' || ptr[i]=='o' ||  ptr[i]=='u' )
                                 ptr[ i ] = toupper(  ptr[ i ] );
                        else
                             ptr[ i ] = ptr[ i ] ;

                    }   


                    printf( "To client: %s",ptr);
                    while (sent < length ){
                        n = write(client_socket, ptr, strlen(ptr) );
                        if ( n == -1) myabort("write()");
                        sent += n;
                        ptr += n;
                    }
                }//end inner while

                close(client_socket);

                //Child exits
                exit(0);
             }


              //Parent Process

            printf("\nChild process spawned with id number:  %d",processid );
            //increment the number of children processes
            childcount++;
            while(childcount){
                processid = waitpid( (pid_t) - 1, NULL, WNOHANG );
                if (processid < 0) myabort("waitpid()");
                else if (processid == 0) break;
                 else childcount--;
            }   

        }
        close(listen_socket);

        exit(0);

    }


    void myabort(char * msg){
        printf("Error!:  %s" ,  msg);
        exit(1);
    }

the client :

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "unistd.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "strings.h"
#include "arpa/inet.h"

#define BUFFER    1024


main(int argc, char **argv)
{
    struct sockaddr_in serv;
    int sock;
    char in[BUFFER];
    char out[BUFFER];
    int len;


    if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    serv.sin_family = AF_INET;
    serv.sin_port = htons(atoi(argv[2]));
    serv.sin_addr.s_addr = inet_addr(argv[1]);
    bzero(&serv.sin_zero, 8);

    printf("\nThe TCPclient %d\n",ntohs(serv.sin_port));
        fflush(stdout);


    if((connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr_in))) == -1)
    {
        perror("connect");
        exit(-1);
    }

    while(1)
    {
        printf("\nInput: ");

        fgets(in, BUFFER, stdin);
        send(sock, in, strlen(in), 0);


        len = recv(sock, out, BUFFER, 0);
        out[len] = '\0';
        printf("Output: %s\n", out);
    }

    close(sock);


}
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Yesbra Bra
  • 11
  • 1
  • 2

3 Answers3

1

One way for two clients to talk to each other is: accept twice before you fork child processes, so both processes know each other.

or

Let server send using UNIX domain socket file descriptor of client B to A, and A to B, for server knows fd of both clients. Check this for unix domain socket(Sending file descriptor over UNIX domain socket, and select())

or

use server as the middle man:

A write to server
Server write to B whild B read from server
B write to server while server read from B
Server write to A while A should read from server
Community
  • 1
  • 1
D3Hunter
  • 1,329
  • 10
  • 21
  • yes ,i have thought of that before , but i do not know exactely how to code it. i know how to connect the server and one client , but the problem is how to get client 2 involved in that (how to make the server to write to the client 2 instead of writing back to client 1) – Yesbra Bra Dec 05 '14 at 15:55
  • 1
    Hello, ihave tried to accept twice and it worked but there is a big problem: i need both clients to write and recieve in the same time how to syncronize both clients . when i run the program, both clients waited for data from the server how to edit the client code so that one must be waiting for data where the other is writing ???? – Yesbra Bra Dec 05 '14 at 23:43
  • In the server create a new thread and handle the message. While your thread is processing the message your server can handle new client – baliman Dec 07 '14 at 06:27
0

I think you have to register your clients by the server and store their socket descriptor in some kind of an array. Each client should have a unique identifier. Also specify some kind of protocol with some information like sender, destination (=client1 or 2) and the message. Your server can handle the message and route your message to the destination.

The protocol can be a simple one like

sender|to|message

for example

client-1|client-2|Hello from client 1

you can also use some xml or any other kind of data structure

On the server side. Extract the message into 3 string parts string-1 : sender (client-1) string-2 : destination (client-2) string 3 : The message (Hello from client 1

The server can than sent the message (i.e. string-3) to client-2

baliman
  • 588
  • 2
  • 8
  • 27
  • but how to exchange ids when sending and recieving messages , i am confused here !!!!! – Yesbra Bra Dec 05 '14 at 12:00
  • client-1 sents a message for destination client-2 and vice versa. You can also decide the server to broadcast a client message to all connected clients (except the one who is sending) – baliman Dec 05 '14 at 12:28
  • your server must hold a list of connected clients – baliman Dec 05 '14 at 12:29
0

I had written a code for the same scenario a few days back. not still proper but it is working just fine and would give u a head start on it

Server side code :-

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


static void   sigchld_handler(int signo) {  
    pid_t PID;   
    int status;  

  do {  
     PID = waitpid(-1,&status,WNOHANG);  
      }   
  while ( PID != -1 );  

// Re-instate handler

  signal(SIGCHLD,sigchld_handler);  

}

  int main(int argc ,char *argv[])
{ 
   int server_socket; 
    int client_socket , size_structure,read_size,binds;
    int *new_socket;
    struct sockaddr_in server, client ;
    server_socket = socket(AF_INET, SOCK_STREAM,0);
    char client_message[100]="";
     pid_t PID;                    /* Process ID */  

/* * Set signal handler for SIGCHLD: */
signal(SIGCHLD,sigchld_handler);

    if(server_socket == -1)
    {  
        puts("socket has nt been created");
    }
    else 
        puts("socket has been created");

    //give values to the structure for server
 server.sin_family = AF_INET;
 server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(2225);

//step 3 bind karo 
binds = bind(server_socket,(struct sockaddr*)&server,sizeof(server));

if(binds<0)
    {
    perror("bind failed.Error");
    return 1;
    } 
    puts("SOcket has been binded to address");

//listen to incoming request

listen(server_socket,30); 
size_structure = sizeof(struct sockaddr_in);
FILE *fp;
fp =fopen("test.txt","w");

while (1)
    {

    client_socket = accept(server_socket,(struct sockaddr *)&client,(socklen_t*)&size_structure);
     if(client_socket<0)
        { 
            puts("client is nt connected");
        return 1;
        }
    else 
        puts("connection accepted");

    if((PID = fork())== -1)
        { 
            close(client_socket);
            continue;
        }

    else if(PID >0)
        {
        close(client_socket);
        continue;
        }

    setlinebuf(fp);

    while(( read_size=recv(client_socket,client_message,2000,0))>0)
        {

        puts(client_message);
            write(client_socket,client_message,sizeof(client_message));
        for(int i=0;i<500;i++)
            { 
            fwrite(client_message,1,sizeof(client_message),fp);
            } 
        if(PID==-1)
            {  
            exit(0);
            }
        memset(client_message,0,strlen(client_message));

        }

    if(read_size==-1)
        {
        puts("client disconnected");
        fflush(stdout);
        close(client_socket);
        exit(0);
        }
    else if(read_size == 0)
        { 
            printf("recveiving failed");
            }
    }



memset(client_message,0,strlen(client_message));
close(client_socket);
fclose(fp);
return 0;

}

Client code :-

   #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;
}
ash123
  • 53
  • 9