migrating recvmsg() to recvfrom()

Discussion in 'C++' started by Wim Deprez, Jul 21, 2004.

  1. Wim Deprez

    Wim Deprez Guest

    Hi group,

    I am trying to port a reliable multicast framework for UNIX to Win32 and so
    far so good, but I stumbled on the next problem:

    in the original code, the programmers use the recvmsg() function and as far
    as I know, there is no Windows-version of this function. So I guess I will
    have to translate it to a recvfrom(), but that gives some problems.

    First of all, in the man pages I read the following:

    <man recvfrom>
    int recvfrom(int s, void *buf, size_t len, int flags,
    struct sockaddr *from, socklen_t *fromlen);

    int recvmsg(int s, struct msghdr *msg, int flags);

    DESCRIPTION

    [...]

    The recvmsg call uses a msghdr structure to minimize the
    number of directly supplied parameters. This structure
    has the following form, as defined in <sys/socket.h>:

    struct msghdr {
    void * msg_name; /* optional address */
    socklen_t msg_namelen; /* size of address */
    struct iovec * msg_iov; /* scatter/gather array */
    size_t msg_iovlen; /* # elements in msg_iov */
    void * msg_control; /* ancillary data, see below
    */
    socklen_t msg_controllen; /* ancillary data buffer len
    */
    int msg_flags; /* flags on received message
    */
    };

    [...]

    The messages are of the form:

    struct cmsghdr {
    socklen_t cmsg_len; /* data byte count, including hdr
    */
    int cmsg_level; /* originating protocol */
    int cmsg_type; /* protocol-specific type */
    /* followed by
    u_char cmsg_data[]; */
    };

    Ancillary data should only be accessed by the macros
    defined in cmsg(3).

    [...]

    </man recvfrom>


    So how do I translate it then?

    if the original code is

    bytes_read=recvmsg(sd, &msg, 0);

    I think it should be the following:

    bytes_read=recvmsg(sd, &msg.msg_control->cmsg_data,
    &msg.msg_control->cmsg_len, 0, (sockaddr *)&msg.msn_name,&msg.msg_namelen);

    anyone has got an idea if my way of thinking is ok here? imho, the framework
    is poorly organized, so I don't find a direct way to test it for only this
    purpose.

    but in for example Cygwin, there is no "msg_control" in the msghdr-struct.
    (/usr/include/cygwin/socket.h)

    Due to absence of experience with msghdr, I have no idea if my translation
    can work and I am looking for a second opinion or other ideas.

    Many kind greetings and thanks in advance,

    --wim
    Wim Deprez, Jul 21, 2004
    #1
    1. Advertising

  2. Wim Deprez

    Wim Deprez Guest

    Hi Group,

    guess I found a solution, I'll post it right here just for the
    threads-sake:

    if you want to port a *nix-program that uses the recvmsg() and
    sendmsg()-functions, you can migrate them by using the following code:

    ssize_t fake_recvmsg(int sd, struct msghdr *msg, int flags)
    {
    ssize_t bytes_read;
    size_t expected_recv_size;
    ssize_t left2move;
    char *tmp_buf;
    char *tmp;
    int i;

    assert(msg->msg_iov);

    expected_recv_size = 0;
    for(i = 0; i < msg->msg_iovlen; i++)
    expected_recv_size += msg->msg_iov.iov_len;
    tmp_buf = malloc(expected_recv_size);
    if(!tmp_buf)
    return -1;

    left2move = bytes_read = recvfrom(sd,
    tmp_buf,
    expected_recv_size,
    flags,
    (struct sockaddr *)msg->msg_name,
    &msg->msg_namelen
    );

    for(tmp = tmp_buf, i = 0; i < msg->msg_iovlen; i++)
    {
    if(left2move <= 0) break;
    assert(msg->msg_iov.iov_base);
    memcpy(
    msg->msg_iov.iov_base,
    tmp,
    MIN(msg->msg_iov.iov_len,left2move)
    );
    left2move -= msg->msg_iov.iov_len;
    tmp += msg->msg_iov.iov_len;
    }

    free(tmp_buf);

    return bytes_read;
    }



    and




    ssize_t fake_sendmsg(int sd, struct msghdr *msg, int flags)
    {
    ssize_t bytes_send;
    size_t expected_send_size;
    size_t left2move;
    char *tmp_buf;
    char *tmp;
    int i;

    assert(msg->msg_iov);

    expected_send_size = 0;
    for(i = 0; i < msg->msg_iovlen; i++)
    expected_send_size += msg->msg_iov.iov_len;
    tmp_buf = malloc(expected_send_size);
    if(!tmp_buf)
    return -1;

    for(tmp = tmp_buf, left2move = expected_send_size, i = 0; i <
    msg->msg_iovlen; i++)
    {
    if(left2move <= 0) break;
    assert(msg->msg_iov.iov_base);
    memcpy(
    tmp,
    msg->msg_iov.iov_base,
    MIN(msg->msg_iov.iov_len,left2move));
    left2move -= msg->msg_iov.iov_len;
    tmp += msg->msg_iov.iov_len;
    }

    bytes_send = sendto(sd,
    tmp_buf,
    expected_send_size,
    flags,
    (struct sockaddr *)msg->msg_name,
    msg->msg_namelen
    );

    free(tmp_buf);

    return bytes_send;
    }


    greetings and have a nice Sunday-evening,

    --wim


    -------------------------
    Many thanks to Lev Walkin
    Wim Deprez, Jul 25, 2004
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. William

    recvfrom gives empty string

    William, Mar 23, 2005, in forum: C++
    Replies:
    2
    Views:
    1,631
    Malte Starostik
    Mar 23, 2005
  2. Heiko Wundram

    Python sockets and recvmsg

    Heiko Wundram, May 2, 2005, in forum: Python
    Replies:
    0
    Views:
    403
    Heiko Wundram
    May 2, 2005
  3. Heiko Wundram

    Re: Python sockets and recvmsg

    Heiko Wundram, May 2, 2005, in forum: Python
    Replies:
    0
    Views:
    354
    Heiko Wundram
    May 2, 2005
  4. Omega

    problem with recvfrom

    Omega, Nov 21, 2005, in forum: C Programming
    Replies:
    9
    Views:
    2,182
  5. Jack
    Replies:
    1
    Views:
    718
    Thomas J. Gritzan
    Feb 1, 2007
Loading...

Share This Page