CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Oct 2009
    Posts
    56

    [RESOLVED] Server/client Chat Program

    I am trying to just make a simple chat program for a server and client to talk to each other with no blocking. I want to be able to send a message at any time and have that pop up on the other's screen when I send it. I am having trouble figuring out how to structure the code to do that (or maybe just using wrong tools). I tried just typical cin and cout, but that blocks. I tried using select(), but I don't think I need that. My latest attempt at it is using the fork process which seems to be the way most threads I have found online do this. However, I am still having trouble doing it. Here is the code

    Server -

    Code:
    //includes taken out
    
    #define PORT "4950"
    #define STDIN 0
    
    struct sockaddr name;
    
    
    
    void set_nonblock(int socket) {
        int flags;
        flags = fcntl(socket,F_GETFL,0);
        assert(flags != -1);
        fcntl(socket, F_SETFL, flags | O_NONBLOCK);
    }
    
    
    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa) {
        if (sa->sa_family == AF_INET)
            return &(((struct sockaddr_in*)sa)->sin_addr);
    
        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    
    int main(int agrc, char** argv) {
        int status, sock, adrlen, new_sd;
    
        struct addrinfo hints;
        struct addrinfo *servinfo;  //will point to the results
    
        //store the connecting address and size
        struct sockaddr_storage their_addr;
        socklen_t their_addr_size;
    
    
        //socket infoS
        memset(&hints, 0, sizeof hints); //make sure the struct is empty
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM; //tcp
        hints.ai_flags = AI_PASSIVE;     //use local-host address
    
        //get server info, put into servinfo
        if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
            exit(1);
        }
    
    
        //make socket
        sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
        if (sock < 0) {
            printf("\nserver socket failure %m", errno);
            exit(1);
        }
    
    
        //allow reuse of port
        int yes=1;
        if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
            perror("setsockopt");
            exit(1);
        }
    
    
    
        //unlink and bind
        unlink("127.0.0.1");
        if(bind (sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
            printf("\nBind error %m", errno);
            exit(1);
        }
    
        freeaddrinfo(servinfo);
    
        //listen
        if(listen(sock, 5) < 0) {
            printf("\nListen error %m", errno);
            exit(1);
        }
    
    
    
        their_addr_size = sizeof(their_addr);
        //accept
        new_sd = accept(sock, (struct sockaddr*)&their_addr, &their_addr_size);
        if( new_sd < 0) {
            printf("\nAccept error %m", errno);
            exit(1);
        }
    
    
        cout<<"\nSuccessful Connection!";
    
    
    
        //set nonblock
        set_nonblock(new_sd);
    
    
        char* in = new char[255];
        char* out = new char[255];
        int numSent;
        int numRead;
        pid_t pid;
    
    
        fork();
        pid = getpid();
    
    
    
        if(pid == 0) {
    
            while( !(out[0] == 'q' && out[1] == 'u' && out[2] == 'i' && out[3] == 't') ) {
    
                fgets(out, 255, stdin);
                numSent = send(sock, out, strlen(out), 0);
    
                if(numSent < 0) {
                    printf("\nError sending %m", errno);
                    exit(1);
                }   //end error
            }   //end while
    
        }   //end child
    
    
        else {
            numRead = recv(sock, in, 255, 0);
            if(numRead < 0) {
                printf("\nError reading %m", errno);
                exit(1);
            }   //end error
            else {
                cout<<in;
                for(int i=0;i<255;i++)
                    in[i] = '\0';
    
            }   //end else
        }   //end parent
    
    
    
        cout<<"\n\nExiting normally\n";
        return 0;
    }


    Client -

    Code:
    //includes taken out
    
    #define PORT "4950"
    
    struct sockaddr name;
    
    
    
    void set_nonblock(int socket) {
        int flags;
        flags = fcntl(socket,F_GETFL,0);
        assert(flags != -1);
        fcntl(socket, F_SETFL, flags | O_NONBLOCK);
    }
    
    
    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa) {
        if (sa->sa_family == AF_INET)
            return &(((struct sockaddr_in*)sa)->sin_addr);
    
        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    
    int main(int agrc, char** argv) {
        int status, sock, adrlen;
    
        struct addrinfo hints;
        struct addrinfo *servinfo;  //will point to the results
    
        memset(&hints, 0, sizeof hints); //make sure the struct is empty
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM; //tcp
        hints.ai_flags = AI_PASSIVE;     //use local-host address
    
        //get server info, put into servinfo
        if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
            exit(1);
        }
    
    
        //make socket
        sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
        if (sock < 0) {
            printf("\nserver socket failure %m", errno);
            exit(1);
        }
    
    
    
        if(connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
            printf("\nclient connection failure %m", errno);
            exit(1);
        }
    
    
    
        cout<<"\nSuccessful connection!";
    
    
    
        //set nonblock
        set_nonblock(sock);
    
        char* out = new char[255];
        char* in = new char[255];
        int numRead;
        int numSent;
        pid_t pid;
    
    
        fork();
        pid = getpid();
    
    
        if(pid == 0) {
    
            while( !(out[0] == 'q' && out[1] == 'u' && out[2] == 'i' && out[3] == 't') ) {
    
                fgets(out, 255, stdin);
                numSent = send(sock, out, strlen(out), 0);
    
                if(numSent < 0) {
                    printf("\nError sending %m", errno);
                    exit(1);
                }   //end error
            }   //end while
        }   //end child process
    
        else {
    
            while( !(in[0] == 'q' && in[1] == 'u' && in[2] == 'i' && in[3] == 't') ) {
            numRead = recv(sock, in, 255, 0);
                cout<<in;
                for(int i=0;i<255;i++)
                    in[i] = '\0';
            }
        }   //end parent process
    
    
        cout<<"\n\nExiting normally\n";
        return 0;
    }
    Whenever I run the code, the server side gets an error when trying to read of "Transport endpoint is not connected" and it happens twice (because of fork I'm guessing?).

    What am I doing wrong here? I feel like I am using fork wrong, but that might just be because I have never used it before. I'm mainly interested in getting the non-blocking i/o to work properly, but any other things you want to point out are welcomed. Thank you for any help.

  2. #2
    Join Date
    Oct 2009
    Posts
    56

    Re: Server/client Chat Program

    Also, I'm doing this in Ubuntu linux, and just opening one terminal and running the server code and another terminal running the client code.

  3. #3
    Join Date
    Oct 2009
    Posts
    56

    Re: Server/client Chat Program

    I am also trying to do it using threads this way -

    server -

    Code:
    #define PORT "4950"
    #define STDIN 0
    
    
    pthread_t readthread;
    pthread_t sendthread;
    
    char* in = new char[255];
    char* out = new char[255];
    int numSent;
    int numRead;
    
    struct sockaddr name;
    
    int sock;
    
    
    
    
    void* readThread(void* threadid) {
    
        while( 1 ) {
    
            numRead = recv(sock, in, 255, 0);
    
            if(numRead > 0) {
                cout<<"\n"<<in;
                for(int i=0;i<strlen(in);i++)
                    in[i] = '\0';
            }   //end if
    
        }   //end while
    }   //END READTHREAD
    
    
    void* sendThread(void* threadid) {
    
        while( 1 ) {
    
            cin.getline(out, 255);
    
            numSent = send(sock, out, 255, 0);
    
            if(numSent > 0) {
                for(int i=0;i<strlen(out);i++)
                    out[i] = '\0';
            }   //end if
    
        }   //end while
    }   //END SENDTHREAD
    
    void set_nonblock(int socket) {
        int flags;
        flags = fcntl(socket,F_GETFL,0);
        assert(flags != -1);
        fcntl(socket, F_SETFL, flags | O_NONBLOCK);
    }
    
    
    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa) {
        if (sa->sa_family == AF_INET)
            return &(((struct sockaddr_in*)sa)->sin_addr);
    
        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    
    int main(int agrc, char** argv) {
        int status, adrlen, new_sd;
    
        struct addrinfo hints;
        struct addrinfo *servinfo;  //will point to the results
    
        //store the connecting address and size
        struct sockaddr_storage their_addr;
        socklen_t their_addr_size;
    
    
        //socket infoS
        memset(&hints, 0, sizeof hints); //make sure the struct is empty
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM; //tcp
        hints.ai_flags = AI_PASSIVE;     //use local-host address
    
        //get server info, put into servinfo
        if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo error: &#37;s\n", gai_strerror(status));
            exit(1);
        }
    
    
        //make socket
        sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
        if (sock < 0) {
            printf("\nserver socket failure %m", errno);
            exit(1);
        }
    
    
        //allow reuse of port
        int yes=1;
        if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
            perror("setsockopt");
            exit(1);
        }
    
    
    
        //unlink and bind
        unlink("127.0.0.1");
        if(bind (sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
            printf("\nBind error %m", errno);
            exit(1);
        }
    
        freeaddrinfo(servinfo);
    
        //listen
        if(listen(sock, 5) < 0) {
            printf("\nListen error %m", errno);
            exit(1);
        }
    
    
    
        their_addr_size = sizeof(their_addr);
        //accept
        new_sd = accept(sock, (struct sockaddr*)&their_addr, &their_addr_size);
        if( new_sd < 0) {
            printf("\nAccept error %m", errno);
            exit(1);
        }
    
    
        cout<<"\nSuccessful Connection!";
    
        //set nonblock
        set_nonblock(new_sd);
    
    
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    
        pthread_create(&readthread, &attr, readThread, (void*)0);
        pthread_create(&sendthread, &attr, sendThread, (void*)1);
    
    
        cout<<"\n\nExiting normally\n";
        return 0;
    }
    client -

    Code:
    #include <iostream>
    #include <string.h>
    #include <cstdlib>
    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    #include <signal.h>
    #include <fcntl.h>
    #include <assert.h>
    #include <iostream>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <pthread.h>
    using namespace std;
    
    #define PORT "4950"
    
    
    pthread_t readthread;
    pthread_t sendthread;
    char* in = new char[255];
    char* out = new char[255];
    int numSent;
    int numRead;
    struct sockaddr name;
    int sock;
    
    
    
    
    void* readThread(void* threadid) {
    
        while( 1 ) {
    
            numRead = recv(sock, in, 255, 0);
    
            if(numRead > 0) {
                cout<<"\n"<<in;
                for(int i=0;i<strlen(in);i++)
                    in[i] = '\0';
            }   //end if
    
        }   //end while
    }   //END READTHREAD
    
    
    void* sendThread(void* threadid) {
    
        while( 1 ) {
            cin.getline(out, 255);
            numSent = send(sock, out, 255, 0);
    
            if(numSent > 0) {
                for(int i=0;i<strlen(out);i++)
                    out[i] = '\0';
            }   //end if
    
        }   //end while
    }   //END SENDTHREAD
    
    
    
    void set_nonblock(int socket) {
        int flags;
        flags = fcntl(socket,F_GETFL,0);
        assert(flags != -1);
        fcntl(socket, F_SETFL, flags | O_NONBLOCK);
    }
    
    
    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa) {
        if (sa->sa_family == AF_INET)
            return &(((struct sockaddr_in*)sa)->sin_addr);
    
        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    
    int main(int agrc, char** argv) {
        int status, adrlen;
    
        struct addrinfo hints;
        struct addrinfo *servinfo;  //will point to the results
    
        memset(&hints, 0, sizeof hints); //make sure the struct is empty
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM; //tcp
        hints.ai_flags = AI_PASSIVE;     //use local-host address
    
        //get server info, put into servinfo
        if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
            exit(1);
        }
    
    
        //make socket
        sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
        if (sock < 0) {
            printf("\nserver socket failure %m", errno);
            exit(1);
        }
    
    
    
        if(connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
            printf("\nclient connection failure %m", errno);
            exit(1);
        }
    
    
    
        cout<<"\nSuccessful connection!";
    
        //set nonblock
        set_nonblock(sock);
    
    
    
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    
        pthread_create(&readthread, &attr, readThread, (void*)0);
        pthread_create(&sendthread, &attr, sendThread, (void*)1);
    
    
        cout<<"\n\nExiting normally\n";
        return 0;
    }

    The problem is that my threads don't loop infinitely like I try to make them do with while(1). I put some couts in the thread functions and it loops about ten times but then stops. The program just says "Successful Connection" and then exiting normally as if nothing else was in the code. I'm not sure if this is a thread or network problem, but I figured I would post it in here in case it helps at all.

  4. #4
    Join Date
    Oct 2009
    Posts
    56

    Re: Server/client Chat Program

    Trying to use select() again worked for me.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured