C - filling TCP socket send buffer

3.7k Views Asked by At

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;
}
2

There are 2 best solutions below

4
user207421 On

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.

0
trev On

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.