0

I just want to wait after I connect my socket to see if I can write into it. So I create & connect my socket and use "select" to do the job, unless ... that don't sort out correctly.

here's my code :

int SocketToBox(char boxIp[INET6_ADDRSTRLEN], int port)
{
    struct sockaddr_in boxAddress;
    int                sock      = -1;

    if ((sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) {
        printf("%s : socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0) : errno = '%s'.\n", __func__, strerror(errno));
        return (-1);
    }

    memset(&boxAddress, 0, sizeof(boxAddress));
    boxAddress.sin_family = AF_INET;
    boxAddress.sin_port = htons(port);
    if (inet_pton(AF_INET, boxIp, &boxAddress.sin_addr) != 1) {
        printf("%s : inet_pton(AF_INET, boxIp<'%s'>, &boxAddress.sin_addr) : errno = '%s'.\n", __func__, boxIp, strerror(errno));
        close(sock);
        return (-1);
    }

    if (connect(sock, (struct sockaddr *)&boxAddress, sizeof(boxAddress)) == -1) {
        if (errno != EINPROGRESS) {
            printf("%s : connect(sock<%d>, (struct sockaddr *)&boxAddress, sizeof(boxAddress)) : errno = '%s'.\n", __func__, sock, strerror(errno));
            close(sock);
            return (-1);
        }
    }
    return (sock);
}



int main(void)
{
    int    sock;
    fd_set writeFdSet;
    char   *message   = "Hello World !";

    if ((sock = SocketToBox("192.192.192.192", 2000)) == -1) {
        printf("%s : SocketToBox(\"192.192.192.192\", 2000) : callstack.\n", __func__);
        return (1);
    }

    FD_ZERO(&writeFdSet);
    FD_SET(sock, &writeFdSet);

    if (select(sock + 1, NULL, &writeFdSet, NULL, NULL) == -1) {
        printf("%s : select(sock<%d> + 1, NULL, &writeFdSet, NULL, NULL) : errno = '%s'.", __func__, sock, strerror(errno));
        return (1);
    }

    if (FD_ISSET(sock, &writeFdSet)) {
        printf("socket UP.\n");

        if (send(sock, message, strlen(message), MSG_DONTWAIT) == -1) {
            printf("%s : send(sock<%d>, message<'%s'>, strlen(message)<%zu>, MSG_DONTWAIT) : errno '%s'.\n", __func__, sock, message, strlen(message), strerror(errno));
            return (1);
        }
        printf("Message sended.\n");
    } else {
        printf("socket DOWN.\n");
    }

    FD_ZERO(&writeFdSet);
    if (sock == -1) {
        close(sock);
    }
    return (0);
}

And my output :

socket UP.
main : send(sock<3>, message<'Hello World !'>, strlen(message)<13>, MSG_DONTWAIT) : errno 'Connection timed out'.

What did I miss ? select return 1, and I don't understand that either ! Why 1 and not 0 ? And why my socket is tagged "writable" by select when a send failed ? I can ensure you that i can't ping 192.192.192.192.

Tom's
  • 2,448
  • 10
  • 22
  • I recommend you start by reading [a `select` manual page](http://man7.org/linux/man-pages/man2/select.2.html), it should explain both behaviors. – Some programmer dude Feb 11 '16 at 18:26
  • Thanks ... really. I already read this select man page and I don't understand the behavior. I will try to turn my question this way : Why a socket, that I purposely connect to nothing, is tagged by select to be writable ? – Tom's Feb 11 '16 at 18:33
  • `SOCK_NONBLOCK` and `MSG_DONTWAIT` are non-standard (i.e., non-POSIX). What operating-system is this for? – Steve Emmerson Feb 11 '16 at 21:04
  • Sorry, I forget to say so : it's Debian. – Tom's Feb 12 '16 at 07:56
  • you may want to read the answer at: `http://stackoverflow.com/questions/10204134/tcp-connect-error-115-operation-in-progress-what-is-the-cause` which is about this same kind of problem. – user3629249 Feb 13 '16 at 17:42

2 Answers2

0

From the select manual page:

On success, select() and pselect() return the number of file descriptors contained in the three returned descriptor sets

That's why the select function returns 1 for you: It returns with one descriptor set in the sets.


For the second problem, also from the manual page:

A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2) without blocking, or a sufficiently small write(2)).

and

those in writefds will be watched to see if space is available for write (though a large write may still block)

So all select will tell you is that there are space available in the descriptors internal buffers, it doesn't say anything about if the data can actually be sent.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Okay, thanks. I haven't understand that at all at the first read of man, but it make sense. The OS just say that he have a buffer ready for writting, not the socket is connected. Guess I will have to find another way to know if a socket is really connected. Thanks. – Tom's Feb 12 '16 at 08:07
0

Because writing to unconnected socket won't block - and this is the only thing select guarantees you.

SergeyA
  • 61,605
  • 5
  • 78
  • 137