So i'm trying to make multiple clients logon to a server through filesockets, and perform simple commands like ls -l, ls, mkdir.

I've managed to make one client recieve output of ls -l command, sometimes, its buggy.

Now i've been sitting for days trying to figure out how to fork() correctly to handle multiple clients, and what sockets to use, close and so on. Perhaps someone can shed some light?

To make it work the client program must be in the same directory as the server program (did not know how to make a path from different folder of client program to the socket).

Client:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCK_PATH "socket"

int main(void)
{
    int s, t, len,i=0;
    struct sockaddr_un remote;
    char str[10000];

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

    printf("Trying to connect...\n");

    remote.sun_family = AF_UNIX;
    strcpy(remote.sun_path, SOCK_PATH);
    len = strlen(remote.sun_path) + sizeof(remote.sun_family);
    if (connect(s, (struct sockaddr *)&remote, len) == -1) {
        perror("connect");
        exit(1);
    }

    printf("Connected.\n");

    while(printf("> "), fgets(str, 10000, stdin), !feof(stdin)) {



        if (send(s, str, strlen(str), 0) == -1) {
            perror("send");
            exit(1);
        }

        if ((t=recv(s, str, 10000, 0)) > 0) {
            str[t] = '\0';
            printf("echo> %s", str);

            for(i=0;i<9999;i++)
            str[i]=NULL;


        } else {
            if (t < 0) perror("recv");
            else printf("Connection with server terminated.\n");
            exit(1);
        }
    }

    close(s);

    return 0;
}

Server:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCK_PATH "socket"


int main( int argc, char *argv[] )
{

    int s, s2, t, len;
    struct sockaddr_un local, remote;
    char str[1000];
    char* arg_list[2220];
    char str1[1000], str2[1000];


    int z=0;
    for(z=0;z<99;z++){
    str1[z] = NULL;
    str2[z] = NULL;
    }

    for(;;){


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

        local.sun_family = AF_UNIX;
        strcpy(local.sun_path, SOCK_PATH);
        unlink(local.sun_path);
        len = strlen(local.sun_path) + sizeof(local.sun_family);
        if (bind(s, (struct sockaddr *)&local, len) == -1) {
            perror("bind");
            exit(1);
        }

        if (listen(s, 5) == -1) {
            perror("listen");
            exit(1);
        }



        printf("Waiting for connections\n");

        t = sizeof(remote);
        if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {   //Server waits for client to connect
            perror("accept");
            exit(1);
        }


        pid_t childPID;

        childPID = fork();

        if(childPID >= 0) // Fork was successful
        {
            if(childPID == 0) // Child process
            {
                printf("\I am child\n");

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

                local.sun_family = AF_UNIX;
                strcpy(local.sun_path, SOCK_PATH);
                unlink(local.sun_path);
                len = strlen(local.sun_path) + sizeof(local.sun_family);
                if (bind(s, (struct sockaddr *)&local, len) == -1) {
                    perror("bind");
                    exit(1);
                    }

                if (listen(s, 5) == -1) {
                    perror("listen");
                    exit(1);
                }


                printf("Connected.\n");



                int        active = 0;
                int done = 0;
                int sent = 0;
                do{

                    int n = recv(s2, str, 1000, 0);
                    if(n <= 0) {
                        if (n < 0) perror("recv");
                            done = 1;
                    }

                    active = 1;

                    str[strcspn ( str, "\n" )] = '\0';  // String stuff below ***

                    strcpy(str1,str);

                    int i=0,k=0;

                    while (str1[i] != ' ')
                        i++;

                    while (str1[i] != '\0'){
                        str2[k] = str1[i+1];
                        k++;
                        i++;
                    }

                    i=0;

                    while (str1[i] != ' ')
                    i++;

                    str1[i] = '\0'; // String stuff above ***


                    int spawn (char* program, char** arg_list)  // Executing the clients command
                    {

                            /*   printf("\n\nprogram = %s\narg_list = %s\n\str1=%s!!!\nstr2=%s\n\n",program,arg_list,str1,str2);*/

                            dup2(s2, STDOUT_FILENO);  //Redericting information to socket
                            dup2(s2, STDERR_FILENO);
                            execvp (program, arg_list);abort ();    // Executing the clients command


                    }


                    char command[2222];


                    char * tmp;

                    i=0;

                    tmp = strtok (command," ");
                    arg_list[0] = tmp;

                    while (tmp != NULL)
                    {
                        tmp = strtok (NULL, " ");
                        arg_list[i+1] = tmp;
                        i++;
                    }

                    char* arg1[] = {
                        str1,
                        NULL
                    };
                    char* arg2[] = {
                        str1,
                        str2,
                        NULL
                    };


                    if (!done && sent == 0 && active == 1){
                        if(str2[0] >= '+' && str2[0] <= 'DEL'){     /* Ugly solution to make commands work.. .sometimes.*/
                            if(str2[1] >= '+' && str2[1] <= 'DEL')

                                spawn (str1, arg2);}
                            else
                                spawn (str1, arg1);
                    }

                    sent = 0;
                    for(z=0;z<99;z++){
                        str1[z] = NULL;
                        str2[z] = NULL;
                    }

                }while (!done);

                //close(s2); // Don't know where to close the sockets

            }
            else //Parent process
            {
                printf("\nI'll just get back to my listening state - the (;;) loop \n");
            //close(s2);
            }

        }
        else // Fork failed
        {
            printf("\nFork failed, quitting!\n");
            return 1;
        }
    }
    return 0;
}

Recommended Answers

All 2 Replies

Very wrong here! First, work out the steps your server needs to take for handling client connections. IE,

  1. Accept connection, getting a socket to communicate with client.
  2. Fork, and let child process handle that socket.
  3. Go back to accepting connection requests in parent process.
  4. When child process is done processing the connection, it terminates (exit).
  5. Don't forget for parent process to wait for signal that child process has terminated, otherwise you end up with a lot of zombie processes.

When you look at what your server does, when it forks, the child process tries to be another root server, accepting connections, and going back to do all this all over, which is not what you want it to do.

  1. I thought i let the child handle the comunication post-accepting, at line
  2. if(childPID == 0){ wich stretches to line 192? Parent process should ignore that code and go back to line 193 and then back to listening/accepting connections.

  3. So the child uses same socket as parent? I thought it was necessary to comunicate through different sockets for different connections? Because while testing some different code i got error "Bind: socket already in use" or something like that.

As for your last comment, i thought i trapped the child in a endless loope at line 99-188 do{ ... while(!done)?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.