code_2_peep
code_2_peep

Reputation: 25

Server is not able to accept() messages from multiple clients?

Two clients are able to connect to the server but it is only accepting and displaying input stream messages for the first client and not for the second, though the other client is also connected.

Following is the code where i am accepting the stream, i have tried closing the socket each tie but it is not working out.

int main(int argc,char *argv[])
{
fd_set ready;
struct sockaddr_in msgfrom;
int msgsize;
union {
    uint32_t addr;
    char bytes[4];
} fromaddr;

if ((progname = rindex(argv[0], '/')) == NULL)
    progname = argv[0];
else
    progname++;
while ((ch = getopt(argc, argv, "adsp:h:")) != -1)
    switch(ch) {
        case 'a':
            aflg++;     /* print address in output */
            break;
        case 'd':
            soctype = SOCK_DGRAM;
            break;
        case 's':
            server = 1;
            break;
        case 'p':
            port = optarg;
            break;
        case 'h':
            host = optarg;
            break;
        case '?':
        default:
            usage();
    }
argc -= optind;
if (argc != 0)
    usage();
if (!server && (host == NULL || port == NULL))
    usage();
if (server && host != NULL)
    usage();
/*
 * Create socket on local host.
 */
if ((s = socket(AF_INET, soctype, 0)) < 0) {
    perror("socket");
    exit(1);
}
sock = setup_server();  
while (!done) {
    FD_ZERO(&ready);
    FD_SET(sock, &ready);
    FD_SET(fileno(stdin), &ready);
    if (select((sock + 1), &ready, 0, 0, 0) < 0) {
        perror("select");
        exit(1);
    }
    if (FD_ISSET(fileno(stdin), &ready)) {
        if ((bytes = read(fileno(stdin), buf, BUF_LEN)) <= 0)
            done++;
        send(sock, buf, bytes, 0);
    }
    msgsize = sizeof(msgfrom);
    if (FD_ISSET(sock, &ready)) {
        if ((bytes = recvfrom(sock, buf, BUF_LEN, 0, (struct sockaddr *)&msgfrom, &msgsize)) <= 0) {
            done++;
        } else if (aflg) {
            fromaddr.addr = ntohl(msgfrom.sin_addr.s_addr);
            fprintf(stderr, "%d.%d.%d.%d: ", 0xff & (unsigned int)fromaddr.bytes[0],
                0xff & (unsigned int)fromaddr.bytes[1],
                0xff & (unsigned int)fromaddr.bytes[2],
                0xff & (unsigned int)fromaddr.bytes[3]);
        }
        write(fileno(stdout), buf, bytes);
    }
}

Here is the code where i am setting up my server, for reference:

int setup_server() {
struct sockaddr_in serv, remote;
struct servent *se;
int newsock, len;

len = sizeof(remote);
memset((void *)&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
if (port == NULL)
    serv.sin_port = htons(9990);
else if (isdigit(*port))
    serv.sin_port = htons(atoi(port));
if (bind(s, (struct sockaddr *)&serv, sizeof(serv)) < 0) {
    perror("bind");
    exit(1);
}
if (getsockname(s, (struct sockaddr *) &remote, &len) < 0) {
    perror("getsockname");
    exit(1);
}
fprintf(stderr, "Port number is %d\n", ntohs(remote.sin_port));
listen(s, 1);
newsock = s;
if (soctype == SOCK_STREAM) {
    fprintf(stderr, "Entering accept() waiting for connection.\n");
    newsock = accept(s, (struct sockaddr *) &remote, &len);
}
return(newsock);
}

Client code:

sock = setup_client();
/*
 * Set up select(2) on both socket and terminal, anything that comes
 * in on socket goes to terminal, anything that gets typed on terminal
 * goes out socket...
 */
while (!done) {
    FD_ZERO(&ready);
    FD_SET(sock, &ready);
    FD_SET(fileno(stdin), &ready);
    if (select((sock + 1), &ready, 0, 0, 0) < 0) {
        perror("select");
        exit(1);
    }
    if (FD_ISSET(fileno(stdin), &ready)) {
        if ((bytes = read(fileno(stdin), buf, BUF_LEN)) <= 0)
            done++;
        send(sock, buf, bytes, 0);
    }
    msgsize = sizeof(msgfrom);
    if (FD_ISSET(sock, &ready)) {
        if ((bytes = recvfrom(sock, buf, BUF_LEN, 0, (struct sockaddr *)&msgfrom, &msgsize)) <= 0) {
            done++;
        } else if (aflg) {
            fromaddr.addr = ntohl(msgfrom.sin_addr.s_addr);
            fprintf(stderr, "%d.%d.%d.%d: ", 0xff & (unsigned int)fromaddr.bytes[0],    0xff & (unsigned int)fromaddr.bytes[1],
                0xff & (unsigned int)fromaddr.bytes[2],
                0xff & (unsigned int)fromaddr.bytes[3]);
        }
        write(fileno(stdout), buf, bytes);
    }
    //close(sock);
}
return(0);
}

/*
 * setup_client() - set up socket for the mode of soc running as a
 *      client connecting to a port on a remote machine.
 */

int setup_client() {

struct hostent *hp, *gethostbyname();
struct sockaddr_in serv;
struct servent *se;

/*
 * Look up name of remote machine, getting its address.
 */
if ((hp = gethostbyname(host)) == NULL) {
    fprintf(stderr, "%s: %s unknown host\n", progname, host);
    exit(1);
}
/*
 * Set up the information needed for the socket to be bound to a socket on
 * a remote host.  Needs address family to use, the address of the remote
 * host (obtained above), and the port on the remote host to connect to.
 */
serv.sin_family = AF_INET;
memcpy(&serv.sin_addr, hp->h_addr, hp->h_length);
if (isdigit(*port))
    serv.sin_port = htons(atoi(port));
else {
    if ((se = getservbyname(port, (char *)NULL)) < (struct servent *) 0) {
        perror(port);
        exit(1);
    }
    serv.sin_port = se->s_port;
}
/*
 * Try to connect the sockets...
 */ 
if (connect(s, (struct sockaddr *) &serv, sizeof(serv)) < 0) {
    perror("connect");
    exit(1);
} else
    fprintf(stderr, "Connected...\n");
return(s);
}

Upvotes: 0

Views: 133

Answers (1)

loreb
loreb

Reputation: 1357

UDP is ok, you can just recvfrom() like you're doing already.

TCP is different, but you're almost there: you need a call to accept() for every connection you wish to handle, ie you shold select() the server socket in the loop, call accept() on it as necessary to get a new socket, deal with it and close() it at the end.

On the client's side it looks like you connected because you're in the server's queue of pending connections -- see the listen(2) manpage.

Upvotes: 1

Related Questions