Darius
Darius

Reputation: 243

How to detect if i have something to read from a socket ? (c++)

i`m trying to recive an answer from a client in a certain amount of s. How could i do that ? I mean i have that code

 unsigned secondsElapsed = 0;
    while(secondsElapsed <= TIMER){
        char tBuffer[32];

    if (recv(clientSocket, tBuffer, sizeof(tBuffer), MSG_PEEK | MSG_DONTWAIT) == 0){
            myPlayer->dcPlayer();
            \\ More stuff to do if player is dissconected
    \\ But if is not dc, and is typing, how can i check my socket to see
    \\ if i have an answer there to read, else i`ll increment 
    \\ secondsElapsed until is equal to TIMER or until i get an answer    
    \\ from my client.

    usleep(1000000);
    secondsElapsed++;
    }

So, the question is: How can i check if my client send me an answer ? If i try to read, then my program will be stuck and i will can`t increment secondsElapsed.

Upvotes: 3

Views: 5884

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595712

You can use select() (or pselect() or (e)poll() on *Nix systems) to know when data is available before you then call recv() (or read()) to read it, eg:

char tBuffer[32];
float secondsElapsed = 0;
clock_t start = clock(), end;

do {
    fd_set rfd;
    FD_ZERO(&rfd);
    FD_SET(clientSocket, &rfd);

    struct timeval timeout;
    timeout.tv_sec = TIMER - secondsElapsed;
    timeout.tv_usec = 0;

    int ret = select(clientSocket+1, &rfd, NULL, NULL, &timeout);
    if (ret == -1) {
        myPlayer->dcPlayer();
        break;
    }

    if (ret == 0) {
        // timeout ...
        break;
    }

    // data available, read it...

    ret = recv(clientSocket, tBuffer, sizeof(tBuffer), 0);
    if (ret <= 0) {
        myPlayer->dcPlayer();
        break;
    }

    // use tBuffer up to ret number of bytes...
    if (... /*no more data is expected*/) {
        break;
    }

    end = clock();
    secondsElapsed = end - start; // time difference is now a float
    seconds /= CLOCKS_PER_SEC; // this division is now floating point
}
while (secondsElapsed <= TIMER);

Upvotes: 1

SergeyA
SergeyA

Reputation: 62563

You have a number of options here. First, you might use non-blocking sockets (usually not-so-great solution). The better option is to use OS-provided polling/async notification mechanism - for example, on *Nix user can choose from select, poll and epoll, while Windows has it's own async event notification API, for example, I/O completion ports, described here: https://msdn.microsoft.com/en-gb/library/windows/desktop/aa365198(v=vs.85).aspx

Upvotes: 5

Related Questions