Michael
Michael

Reputation: 61

Socket Programming, Server w/ Multiple Clients in C

I am running into some problem with my server. I am trying to reading inputs from multiple clients but I can only do it one at a time. I think my server's code does not have an issue. So I assume that my local clients are the ones that are actually at fault here. Are each clients exactly the same as the other if I want to handle multiple clients with different sockets. or are they different in some ways?

What do you guys think?

Server.c

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

//char *socket_path = "./socket";
char *socket_path = "\0hidden";

int main(int argc, char *argv[]) {
    struct sockaddr_un addr;
    //max client sockets
    int max_sd, sd, i, client_socket[3], activity;
    char buf[100];
    int fd,cl,rc;
    fd_set readfds;

    if (argc > 3) socket_path=argv[3];

    //establish socket
    if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket error");
        exit(-1);
    }

    //establish socket name
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);

    unlink(socket_path);

    //bind socket
    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind error");
        exit(-1);
    }

    //listen to the socket
    if (listen(fd, 5) == -1) {
        perror("listen error");
        exit(-1);
    }

    while (1) {

        //clear the scoket set
        FD_ZERO(&readfds);

        //add fd socket to set
        FD_SET(fd, &readfds);
        max_sd = fd;

        //add child sockets to the set
        for(i = 0; i < 3; i++) {
            sd = client_socket[i];

            if(sd > 0) {
                FD_SET( sd, &readfds);
            }

            if(sd > max_sd) {
                max_sd = sd;
            }
        }

        //wait for an activity from a socket
        activity = select(max_sd + 1, &readfds,NULL, NULL,NULL);

        if((activity < 0) && (errno!=EINTR)) {
            printf("select");
        }

        if(FD_ISSET(fd, &readfds)) {

            if ( (cl = accept(fd, NULL, NULL)) == -1) {
                perror("accept error");
                continue;
            }

            while ( (rc=read(cl,buf,sizeof(buf))) > 0) {
                printf("read %u bytes: %.*s\n", rc, rc, buf);
            }
            if (rc == -1) {
                perror("read");
                exit(-1);
            }
            else if (rc == 0) {
                printf("EOF\n");
                close(cl);
            }   
        }
    }
    return 0;
}

Upvotes: 0

Views: 1181

Answers (2)

user4822941
user4822941

Reputation:

What?

//wait for an activity from a socket
activity = select(max_sd + 1, &readfds,NULL, NULL,NULL);

if((activity < 0) && (errno!=EINTR)) {
    printf("select");
}
if(FD_ISSET(fd, &readfds)) {

if ( (cl = accept(fd, NULL, NULL)) == -1) {

Accepting a connection...

  perror("accept error");
  continue;
}

while ( (rc=read(cl,buf,sizeof(buf))) > 0) {
  printf("read %u bytes: %.*s\n", rc, rc, buf);
}

Blocking read until there is no error... (with incorrect printf)

if (rc == -1) {
  perror("read");
  exit(-1);
}
else if (rc == 0) {
  printf("EOF\n");
  close(cl);
}

Incorrect, but assuming no real errors means reading till the other party closes their side.

With this in mind, how was this supposed to support several clients at once?

Read this: http://www.kegel.com/c10k.html

Upvotes: 1

Matthew
Matthew

Reputation: 302

I don't know how sockets work in C, but I've been working on some Java programs, and the solution to your problem, in java, is to provide a separate thread on the server for each client. Each time a client connects to the server, you start a thread that will serve that client. A fork will help maybe.

Upvotes: 0

Related Questions