Thread: Simple client - receiving data from server and keyboard w/o blocking

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    22

    Simple client - receiving data from server and keyboard w/o blocking

    Hi everyone. I'm building a simple chat server/client using c++ and Winsock and I've run into a problem with my client. I'm combining two examples from Beej's Networking Guide to try and use select() to accept input from the keyboard if there is nothing to receive.

    Here's my code (stripped down):
    Code:
    #include <string>
    #include <iostream>
    #include <winsock.h>
    
    #define STDIN 0
    
    void error (const char * error) {
        std::cout<<"Error with "<<error<<"\n"<<WSAGetLastError();
    }
    
    int main(int argc, char *argv[]) {
        
        SOCKET sockfd;
        
        // ....
        // whole bunch of initialisation stuff
        // ....
        
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            error("socket");
            exit(1);
        }
        
        // etc
        // ......
        
        fd_set readfds;
        fd_set master;
        
        FD_ZERO(&master);
        FD_ZERO(&readfds);
        
        FD_SET(STDIN, &master);
        FD_SET(sockfd, &master);
        
        // ....
        
        int nbytes;
        
        timeval tv;
        tv.tv_sec = 2;
        tv.tv_usec = 500000;
        
        if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
            error("connect");
            return 1;
        }
        
        while (1) {
            readfds = master;
            
            if (select(sockfd+1, &readfds, NULL, NULL, &tv) == -1) {
                error("select");
                return 1;
            }
            
            for (int i = 0; i <= sockfd; i++) {
    
                if (FD_ISSET(i, &readfds)) {
    
                        if (i == STDIN) {
    
                            // don't think i should be using cin here. how do i do it?
                            std::cin>>message;
                            
                            // ...
                            
                            send(sockfd, sendbuffer.c_str(), length, 0);
                            
                        } else {
    
                            // receive data from server?
                            nbytes = recv(i, recvbuffer, 1, 0);
                            
                            // ... 
                            
                        }
                }
            }
        }
    
            return 0;
    }
    If you need more code just tell me, I've tried to take out all the irrelevant stuff. Any help would be greatly appreciated.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Windows select is broken, it only works on socket descriptors (non socket descriptors like stdin are not allowed).
    You're unlikely to be able to use cin either, since that's almost certainly buffered somewhere. You would need to use the low-level win32 console functions to "peek" to see if there was any data available.

    Code:
    while ( 1 ) {
      if ( select() ) {
        // do something with network data
      }
      if ( SomeWin32ConsolePeekingFunction() ) {
        // do something with keyboard data
      }
      // do something else
    }

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    22
    Alright, thanks. I'll look into that

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    To "Peek" for console input:
    Code:
      #include <winsock2.h>
      ...
      HANDLE consoleInputHandle = GetStdHandle(STD_INPUT_HANDLE);
      ...
      if(WaitForSingleObject(consoleInputHandle, 0) == WAIT_OBJECT_0)
       //Then there is keyboard input waiting
      
      //And then, not sure if you need to CloseHandle(consoleInputHandle) or not...
      //MSDN didn't say so, but maybe they forgot or something.
    Alternately, if your compiler has kbhit() (it's nonstandard):
    Code:
     #include <conio.h>  //nonstandard!!
     ...
      if(kbhit())
         //then there's keyboard input waiting
    Last edited by Hunter2; 01-06-2005 at 09:54 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #5
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    I would suggest fork() for unix,
    and threads for windows.

    to create a multi-process program.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  6. #6
    Registered User
    Join Date
    Dec 2004
    Posts
    95
    Creating threads creates a multithreaded program, the threads are all part of the same process.

    Fork does indeed spawn new processes.

Popular pages Recent additions subscribe to a feed