3

I'm trying to write an experimental client / server program to prove whether the write fails or blocks when the send buffer is full. Basically, I have an infinite loop on the sender program where I use select() to check if I can write on the buffer (which, I think means that the socket buffer isn't full), if I can write on the buffer than I write() a character. The loop breaks when FD_ISSET(sockfd, &writefds) is false (I can't write on the buffer because it's full). The reciever program is sleeping for one minute before starting to read(). I expect the sender to fill the buffer within this sleeping time but in fect, the programs never end.

sender:

int main(int argc, char *argv[]) {
    char buffer[100];
    int sockfd, total = 0, bytes = 0;
    fd_set writefds;

    sockfd = dial(argv[1], argv[2]);
    bzero(buffer, sizeof buffer);

    while(1)
    {
        int ret = 0;
        FD_ZERO(&writefds);
        FD_SET(sockfd, &writefds);

        if((ret = select(sockfd + 1, NULL, &writefds, NULL, 0)) < 0)
        {
            perror("select");
            exit(errno);
        }

        if(FD_ISSET(sockfd, &writefds))
        {
            write(sockfd, "a", 1);
            total++;
            continue;
        }
        else
        {
            puts("I can't write in the socket buffer");
            break;
        }
    }
    printf("nb chars written: %d\n", total);

    return 0;
}

reciever:

int foo(int sockfd) {
    char buffer[100];
    int t, total = 0;

    bzero(buffer, sizeof buffer);
    printf("I have a new client\n");

    sleep(60);

    while((t = read(sockfd, buffer, sizeof buffer)) > 0)
    {
        total += t;
        printf("%d ", total);
    }
    printf("nb chars read: %d\n", total);

    if(t < 0)
    {
        perror("read");
    }

    printf("I don't have that client anymore\n");
    return 0;
}
rtruszk
  • 3,902
  • 13
  • 36
  • 53
selfm
  • 101
  • 1
  • 9
  • you should add your code for creating the socket to make sure it is connection oriented and not UDP. – trev Oct 20 '14 at 08:35

2 Answers2

0

You're on the right track, but the socket send buffer could be 48k or more. That's a lot of iterations. Try writing 8k at a time, not just one byte. And increase the time before the receiver reads.

NB No real need to test this. It blocks in blocking mode, and fails with EAGAIN/EWOULDBLOCK in non-blocking mode. See the man page.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thanks a lot for your answer. I've editing my code to write a lot more at each write() call and waiting for a longer time. I've noticed with a printf() that the sender stop writing at a random number of bytes after 2600000 bytes. Than it wait the time for the reciever to read the buffer (I guess) and then start writing endlessly. But I never get the "I can't write in the socket buffer" message. – selfm Mar 31 '14 at 12:38
  • Is the sending socket in non-blocking mode? If it isn't, it will *block* while the send buffer is full. – user207421 Mar 31 '14 at 13:54
  • The sending socket isn't in non-blocking mode. I think that the write() do block but just for a moment and it starts writing forever then. I can't manage to understand why if(FD_ISSET(sockfd, &writefds)) is always false. – selfm Mar 31 '14 at 18:15
  • I don't understand the difference between 'block' and 'writing forever'. As the socket blocks while the send buffer is full, your select() is never getting a chance to see that. Try non-blocking mode. – user207421 Mar 31 '14 at 23:20
0

Your select timeout is null, so select() will block when the send buffer is full. This means when it returns, the socket is writable, and you'll never get to your code "I can't write in the socket buffer".

See man page http://linux.die.net/man/2/select

If you want a zero timeout, i.e. don't block on select(), you need to pass a pointer to a timeval structure with both fields set to zero.

trev
  • 669
  • 1
  • 6
  • 9