Ataul Haque
Ataul Haque

Reputation: 1

Stuck with i/o multiplexing

/* Server.c */
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include <string.h>
#define SERV_TCP_PORT 25000

#define BUFSIZE 1024

void login(char *buffer, int i, int j, int sockfd, fd_set master, int fdmax);

void login(char *buffer, int i, int j, int sockfd, fd_set master, int fdmax){
    char user[BUFSIZE] = "user", pass[BUFSIZE] = "12345";
    char username[BUFSIZE], password[BUFSIZE];
    
    recv(i, username, BUFSIZE, 0);
    for (j = 0; j <= fdmax; j++) {
        if (FD_ISSET(j, &master)) {
            if (j != sockfd && j== i) { // to itself but not all
                if (j!=sockfd) {
                    printf("Username receive [%s] from socket [ %d ]\n", username, i);
                    if(strcmp(username, user)==0) 
                    {
                        send(j, username, BUFSIZE, 0);
                        printf("\nSend the username [ %s ] via socket [%d]\n", username, j);
                        //bzero(buffer, BUFSIZE);

                        recv(i, password, BUFSIZE, 0);

                        for (j = 0; j <= fdmax; j++) {
                            if (FD_ISSET(j, &master)) {
                                if (j != sockfd && j== i) { // to itself but not all
                                    if (j!=sockfd) {
                                        printf("Password [%s] from socket [ %d ]\n", password, i);
                            
                                        if(strcmp(password, pass)==0) 
                                        {
                                            send(j, password, BUFSIZE, 0);
                                            printf("\nSend the password [ %s ] via socket [%d]\n", password, j);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

int main(int argc, char** argv){
    fd_set master;
    fd_set read_fds;
    struct sockaddr_in myaddr;
    struct sockaddr_in remoteaddr;
    int fdmax;
    int sockfd;
    int new_sockfd;
    char buffer[BUFSIZE];
    int nbytes;
    int yes = 1;
    int addrlen;
    int i, j;
    pid_t pid;

    sigset_t set1;
    sigemptyset(&set1);
    sigaddset(&set1, SIGTSTP); //ctrl+z
    sigprocmask(SIG_BLOCK, &set1, NULL);

    FD_ZERO(&master);
    FD_ZERO(&read_fds);

    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0) ) == -1){
        printf("\nsocket() error!!!\n");
        exit(1);}

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
        printf("\nSetsockopt() error!!!\n");
        exit(1);}
    
    bzero( (char *)&myaddr, sizeof(myaddr) );
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = INADDR_ANY;
    myaddr.sin_port = htons(SERV_TCP_PORT);
    bzero(&(myaddr.sin_zero), 8);

    if (bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1){
        printf("\nbind() error!!!\n");
        exit(1);}

    if (listen(sockfd, 10) == -1){
        printf("\nlisten() error!!!\n");
        exit(1);}
    
    FD_SET(sockfd, &master);
    fdmax = sockfd;  // only sockfd at this moment

    for(;;){
        read_fds = master;
        if (pselect(fdmax+1, &read_fds, NULL, NULL, NULL, &set1) == -1){
            printf("\nselect() error!!!\n");
            exit(1);                }
        for(i=0; i<=fdmax; i++)     {
            if( FD_ISSET(i, &read_fds) ){
                if (i == sockfd) {
                    addrlen = sizeof(remoteaddr);
                    if( (new_sockfd = accept(sockfd, &remoteaddr, &addrlen) ) == -1 ) {
                        printf("\naccept() error!!!\n");} 
                    else {
                        FD_SET(new_sockfd, &master);
                        if(new_sockfd > fdmax){
                            fdmax = new_sockfd;}
                        printf("selectserver: new connection from %s on socket %d \n", inet_ntoa(remoteaddr.sin_addr), new_sockfd);
                    
                    } // esle for accept()
                } // else for i==sockfd
                else
                {  // if i != sockfd

                    
                    if (nbytes = recv(i, buffer, sizeof(buffer), 0) <=0) {
                        if (nbytes == 0) {
                            printf("selectserver: socket %d hung up\n", i); } 
                        else{
                            printf("\nrecv() error!!!\n"); } // else for nbytes == 0
                
                            close(i);
                            FD_CLR(i, &master); } // for recv
                    else{
                        
                        for (j = 0; j <= fdmax; j++)
                        {
                            if (FD_ISSET(j, &master)) {
                                if (j != sockfd && j == i) { // to itself but not all
                                    if (j!=sockfd) 
                                    {
                                        printf("Message [ %s ] from socket [ %d ] client [ %s ] \n", buffer, i, inet_ntoa(remoteaddr.sin_addr) );
                                        if(strcmp(buffer, "start")==0){
                                            //printf("Message [%s] from socket [ %d ] client [ %s ] \n", buffer, i, inet_ntoa(remoteaddr.sin_addr) );
                                            send(j, buffer, BUFSIZE, 0);
                                        
                                            login(buffer, i, j, sockfd, master, fdmax); 
                                        }
                                        else if(strcmp(buffer, "exit")==0){
                                            printf("\nrecv() error!!!\n");
                                            close(i);
                                            FD_CLR(i, &master);
                                            //break;
                                        }
                                    } 
                                } 
                            }
                        }
                    }
                }
            }
        }
    }
    return 0;
}

This is server.c

/* Client.c */

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>

#include<string.h>
#define SERV_TCP_PORT 25000

#define BUFSIZE 1024

int main(int argc, char *argv[])
{
    int sockfd;
    char buffer[BUFSIZE+1];

    struct sockaddr_in serv_addr;

    bzero((char *)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_TCP_PORT);
    inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);

    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        perror("\nsocket() error!!!\n");
    }

    if( (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr) )) < 0){
        perror("\nconnect() error!!!\n");
    }

    printf("\nconnection with server: %s...\n", inet_ntoa(serv_addr.sin_addr));

    do
    {
        bzero(buffer, BUFSIZE);
        printf("\nEnter a message : [type /q to quit]");
        scanf("%s", buffer);
        printf("\nMessage [ %s ] send to server \n", buffer);

        send(sockfd, buffer, BUFSIZE, 0);
        bzero(buffer, sizeof(buffer));

        recv(sockfd, buffer, BUFSIZE, 0);
        printf("\nMessage [ %s ] received from server \n", buffer);
    } while (strcmp(buffer, "/q"));
    

    close(sockfd);

}

This is client.c

I want to solve the problem with Server.c, but it can't handle multiple clients simultaneously. When I am trying to take input from second client, it hang. The second client begins working after first client done his job.

Upvotes: 0

Views: 82

Answers (1)

Jeremy Friesner
Jeremy Friesner

Reputation: 73161

I see several errors in the code.

When I compile server.c, I get this warning from clang:

server.c:128:32: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
                    if (nbytes = recv(i, buffer, sizeof(buffer), 0) <=0) {

I think you intended this instead:

if ((nbytes = recv(i, buffer, sizeof(buffer), 0)) <=0)

Also on line 137 you have this:

if (FD_ISSET(j, &master)) {

... but master doesn't contain the results of your latest pselect() operation, so you probably wanted to do this instead:

if (FD_ISSET(j, &read_fds)) {

Once I corrected those two problems, I could connect to your server with telnet localhost 25000 and get reasonable behavior from it.

However, connecting with your client program resulted in only the first entered line of text being received. That is because your client blocks inside recv(sockfd, buffer, BUFSIZE, 0), and therefore will not process any further lines of text entered into stdin until after it has received some data from the server. If that's intentional behavior, then it's okay, but if you were intending for the clients to be able to send data to the server whenever the user enters text into stdin, you should probably update your client program to use select() in a way similar to how your server does. (On POSIX OS's [not Windows], you can have select() monitor STDIN_FILENO and treat stdin as if it was any other file-descriptor)

Upvotes: 1

Related Questions