POSIX's send() on non blocking sockets may partially write? - Unix

This is a discussion on POSIX's send() on non blocking sockets may partially write? - Unix ; Hello I am trying to determine by reading the POSIX specification if a conforming send() implementation on a non blocking socket is allowed to return on partial writes. From what I understand if the socket is non blocking and if ...

+ Reply to Thread
Results 1 to 9 of 9

Thread: POSIX's send() on non blocking sockets may partially write?

  1. POSIX's send() on non blocking sockets may partially write?

    Hello

    I am trying to determine by reading the POSIX specification if a
    conforming send() implementation on a non blocking socket is allowed
    to return on partial writes. From what I understand if the socket is
    non blocking and if there isn't enough space in the buffer for the
    data to send then send will fail with EAGAIN. If however there is
    enough space it will succeed with all bytes written is it not?

    Example,
    int res = send(sock, "1", 2, MSG_DONTWAIT);
    (MSG_DONTWAIT is not standard but just imagine that instead of it the
    socket "sock" is non blocking)

    Can I assume for a conforming POSIX implementation that "res" will be
    either -1 (and errno set to whatever error happened) or be 2 (fully
    successful send)? If not can you describe a case where it may not be
    so?

    Thanks!

    --
    Dizzy


  2. Re: POSIX's send() on non blocking sockets may partially write?

    On Sep 4, 7:18 am, dizzy wrote:
    > Hello
    >
    > I am trying to determine by reading the POSIX specification if a
    > conforming send() implementation on a non blocking socket is allowed
    > to return on partial writes. From what I understand if the socket is
    > non blocking and if there isn't enough space in the buffer for the
    > data to send then send will fail with EAGAIN. If however there is
    > enough space it will succeed with all bytes written is it not?
    >
    > Example,
    > int res = send(sock, "1", 2, MSG_DONTWAIT);
    > (MSG_DONTWAIT is not standard but just imagine that instead of it the
    > socket "sock" is non blocking)
    >
    > Can I assume for a conforming POSIX implementation that "res" will be
    > either -1 (and errno set to whatever error happened) or be 2 (fully
    > successful send)? If not can you describe a case where it may not be
    > so?


    AFAIK, send(2)/write(2) can always do a partial write, even in non-
    blocking mode. In your example, if only one byte is available in the
    buffer, send() should put one byte into the buffer and return 1. So
    you need to prepare for this eventuality.

    The wording in the FreeBSD man page makes it more clear: "If no
    messages space is available at the socket to hold the message to be
    transmitted, then send() normally blocks, unless the socket has been
    placed in non-blocking I/O mode". So blocking or EAGAIN happens only
    when the buffer is completely full.

    This makes sense if you think about it. Suppose that, unbeknownst to
    you, your socket has a buffer that is only one byte long. Under the
    semantics you propose, trying to send() 2 bytes would result in an
    EAGAIN. You would ordinarily wait and try again later, but the call
    would never succeed. However, if send() writes one of the bytes, then
    progress is made and eventually everything will be written.
    (Replacing 1 and 2 with more realistic numbers will give a more
    realistic example.)

  3. Re: POSIX's send() on non blocking sockets may partially write?

    fjblurt@yahoo.com wrote:

    > AFAIK, send(2)/write(2) can always do a partial write, even in non-
    > blocking mode. In your example, if only one byte is available in the
    > buffer, send() should put one byte into the buffer and return 1. So
    > you need to prepare for this eventuality.


    I'm fairly sure that your "always" is incorrect.

    While for a stream socket partial writes make sense, what about pipes
    and datagram sockets? In the case of pipes, writes below a certain size
    must be atomic, and for datagrams it makes no sense to do a partial write.

    Chris

  4. Re: POSIX's send() on non blocking sockets may partially write?

    Chris Friesen writes:
    > fjblurt@yahoo.com wrote:
    >> AFAIK, send(2)/write(2) can always do a partial write, even in non-
    >> blocking mode. In your example, if only one byte is available in the
    >> buffer, send() should put one byte into the buffer and return 1. So
    >> you need to prepare for this eventuality.

    >
    > I'm fairly sure that your "always" is incorrect.
    >
    > While for a stream socket partial writes make sense, what about pipes
    > and datagram sockets? In the case of pipes, writes below a certain
    > size must be atomic, and for datagrams it makes no sense to do a
    > partial write.


    Ehh ... all writes targetting datagram sockets must be atomic (or
    return an error). There is no way to 'preserve message boundaries'
    otherwise.

    Regarding the original question: I feel strongly inclined to assume
    that this refers to the 'possibility' to use TCP for
    message boundary preserving transmissions. And this isn't possible.

  5. Re: POSIX's send() on non blocking sockets may partially write?

    On Sep 4, 7:18*am, dizzy wrote:

    > I am trying to determine by reading the POSIX specification if a
    > conforming send() implementation on a non blocking socket is allowed
    > to return on partial writes. From what I understand if the socket is
    > non blocking and if there isn't enough space in the buffer for the
    > data to send then send will fail with EAGAIN. If however there is
    > enough space it will succeed with all bytes written is it not?


    It totally depends on the protocol. The rules for files are nothing
    like the rules for pipes which are nothing like the rules for datagram
    sockets which are different from the rules for stream sockets.

    DS

  6. Re: POSIX's send() on non blocking sockets may partially write?

    fjblurt@yahoo.com wrote:

    > On Sep 4, 7:18 am, dizzy wrote:
    >> Hello
    >>
    >> I am trying to determine by reading the POSIX specification if a
    >> conforming send() implementation on a non blocking socket is
    >> allowed to return on partial writes. From what I understand if the
    >> socket is non blocking and if there isn't enough space in the
    >> buffer for the data to send then send will fail with EAGAIN. If
    >> however there is enough space it will succeed with all bytes
    >> written is it not?
    >>
    >> Example,
    >> int res = send(sock, "1", 2, MSG_DONTWAIT);
    >> (MSG_DONTWAIT is not standard but just imagine that instead of it
    >> the socket "sock" is non blocking)
    >>
    >> Can I assume for a conforming POSIX implementation that "res" will
    >> be either -1 (and errno set to whatever error happened) or be 2
    >> (fully successful send)? If not can you describe a case where it
    >> may not be so?

    >
    > AFAIK, send(2)/write(2) can always do a partial write, even in non-
    > blocking mode. In your example, if only one byte is available in
    > the
    > buffer, send() should put one byte into the buffer and return 1. So
    > you need to prepare for this eventuality.
    >
    > The wording in the FreeBSD man page makes it more clear: "If no
    > messages space is available at the socket to hold the message to be
    > transmitted, then send() normally blocks, unless the socket has been
    > placed in non-blocking I/O mode". So blocking or EAGAIN happens
    > only when the buffer is completely full.


    That seems to be not what POSIX says:
    "If space is not available at the sending socket to hold the message to be transmitted, and the socket file descriptor does not have
    O_NONBLOCK set, send() shall block until space is available. If space
    is not available at the sending socket to hold the message to be
    transmitted, and the socket file descriptor does have O_NONBLOCK set,
    send() shall fail."

    My reading of "to hold the message" means it needs to have space for
    the full data to be sent otherwise it returns with EAGAIN.

    > This makes sense if you think about it. Suppose that, unbeknownst
    > to
    > you, your socket has a buffer that is only one byte long. Under the
    > semantics you propose, trying to send() 2 bytes would result in an
    > EAGAIN.


    Well then the POSIX wording is wrong? I would have wanted a EMSGSIZE
    in that case but that's probably sent only for datagram sockets.

    --
    Dizzy


  7. Re: POSIX's send() on non blocking sockets may partially write?

    On Sep 8, 5:08*am, dizzy wrote:

    > That seems to be not what POSIX says:
    > "If space is not available at the sending socket to hold the message to be transmitted, and the socket file > descriptor does not have
    > O_NONBLOCK set, send() shall block until space is available. If space
    > is not available at the sending socket to hold the message to be
    > transmitted, and the socket file descriptor does have O_NONBLOCK set,
    > send() shall fail."


    > My reading of "to hold the message" means it needs to have space for
    > the full data to be sent otherwise it returns with EAGAIN.


    No, that is not correct. The "full data to be sent" only constitutes a
    message for protocols that honor message boundaries. For protocols
    like TCP, the "full data to be sent" is not a message because there
    are no message boundaries.

    > Well then the POSIX wording is wrong? I would have wanted a EMSGSIZE
    > in that case but that's probably sent only for datagram sockets.


    Stream sockets (like TCP) do not send messages.

    DS

  8. Re: POSIX's send() on non blocking sockets may partially write?

    David Schwartz wrote:

    > On Sep 8, 5:08 am, dizzy wrote:
    >> My reading of "to hold the message" means it needs to have space
    >> for the full data to be sent otherwise it returns with EAGAIN.

    >
    > No, that is not correct. The "full data to be sent" only constitutes
    > a message for protocols that honor message boundaries. For protocols
    > like TCP, the "full data to be sent" is not a message because there
    > are no message boundaries.


    OK, so POSIX is fine to say about send() that it always fails with
    EAGAIN on non blocking sockets when there is no space for the message
    to be sent and what I missed is the definition of "message". In case
    of message based protocols it's defined by the protocol details and in
    the case of PF_INET/SOCK_STREAM/IPPROTO_TCP a message is a byte then?

    What about the (not sure if standard) SO_SNDLOWAT socket option. By
    default I know it's "1" and increasing it means that even for TCP/IP
    EAGAIN will be returned if available buffer size is lower than the
    SO_SNDLOWAT value?

    >> Well then the POSIX wording is wrong? I would have wanted a
    >> EMSGSIZE in that case but that's probably sent only for datagram
    >> sockets.

    >
    > Stream sockets (like TCP) do not send messages.


    But the POSIX reference doesn't say anything about non blocking
    semantics of send() other than that sentence which mentions "message".
    So it means TCP does have a message only that is always 1 byte size
    (or something like that).

    --
    Dizzy

  9. Re: POSIX's send() on non blocking sockets may partially write?

    On Sep 9, 7:09*am, dizzy wrote:

    > OK, so POSIX is fine to say about send() that it always fails with
    > EAGAIN on non blocking sockets when there is no space for the message
    > to be sent and what I missed is the definition of "message". In case
    > of message based protocols it's defined by the protocol details and in
    > the case of PF_INET/SOCK_STREAM/IPPROTO_TCP a message is a byte then?


    There are no messages for TCP. TCP is not a message-based protocol.

    > What about the (not sure if standard) SO_SNDLOWAT socket option. By
    > default I know it's "1" and increasing it means that even for TCP/IP
    > EAGAIN will be returned if available buffer size is lower than the
    > SO_SNDLOWAT value?


    Maybe. I would strongly advise not messing with SO_SNDLOWAT.

    > > Stream sockets (like TCP) do not send messages.


    > But the POSIX reference doesn't say anything about non blocking
    > semantics of send() other than that sentence which mentions "message".
    > So it means TCP does have a message only that is always 1 byte size
    > (or something like that).


    TCP does not have messages. TCP is a byte-stream protocol. All it has
    is bytes. The POSIX documentation is not extremely well organized on
    this. You have to find the sections that tell you which sections
    apply.

    DS

+ Reply to Thread