How to solve: sending UDP packet using Sendto() got "message too long"

32,369

Solution 1

You can not send messages (datagrams) larger than 2^16 65536 octets with UDP. The length field of a UDP packet is 16 bits. The buffer sizes you're requesting are not about the size for a packet, but how many octets the OS does buffer incoming and outgoing in total (spread over multiple packets). But a single packet can not get larger.

Solution 2

Per @datenwolf's answer, you simply can't send more than 64k in a single UDP datagram, as that limit is implicit in the two-byte length field in the protocol.

Furthermore, it's not actually a good idea to send even that much at once. You should limit your packets to the MTU on the path between the two ends (typically in the region of 1500 bytes or less) so that you don't get fragmentation in the IP layer.

Fragmentation is bad - ok?

Solution 3

Why not just call sendto several times, with an offset into the buffer?

int sendto_bigbuffer(int sock, const void *buffer, const size_t buflen, int flags,
                     const struct sockaddr *dest_addr, socklen_t addrlen)
{
    size_t sendlen = MIN(buflen, 1024);
    size_t remlen  = buflen;
    const void *curpos = buffer;

    while (remlen > 0)
    {
        ssize_t len = sendto(sock, curpos, sendlen, flags, dest_addr, addrlen);
        if (len == -1)
            return -1;

        curpos += len;
        remlen -= len;
        sendlen = MIN(remlen, 1024);
    }

    return buflen;
}

Something like the above function will send the buffer 1024 bytes at a time.

Share:
32,369
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I want to use the sendto() API to send video and audio data through UDP packet. The sending buffer size I got using getsockopt() is 114688, however, sendto() returned -1 when the data packet less than 65536 not 114688. And the error message is Message too long.

    When I used setsockopt() to adjust the sending buffer size as 200000, I used getsockopt() and found the sending buffer size was not 200000 but 262142. So I still got the same error when I sent data packet with a size bigger than 65536.

    I am confused about this situation. I want to know what the reason is and how to solve this problem.

    When I used FFMPEG library to send the video and audio packet, there is no error. So I am sure there is a solution for this problem and I missed something.

    Is there anyone can help me about this problem? I really can not understand what the reason is.

    The OS I used is ubuntu 11.04,I got the same results in ubuntu 11.10.

    That is the code I used to create socket and configure the parameter:

    unsigned char *output_buffer = (unsigned char*)av_malloc(IO_BUFFER_SIZE);
    if (NULL == output_buffer) {
        printf("Couldn't allocate input buffer.\n");
        return NULL;
    }
    
    output_context_data_t *context_data = (output_context_data_t *)malloc(sizeof(output_context_data_t));
    if (NULL == context_data) {
        printf("Could not allocate output context data.\n");
        av_free(output_buffer);
        return NULL;
    }
    
    context_data->socket = socket(AF_INET, SOCK_DGRAM, 0);
    if(context_data->socket < 0) {
        printf("socket creating fail!\n");
        return NULL;    
    }
    
    context_data->socket_addr->sin_family = AF_INET;
    context_data->socket_addr->sin_port = htons(output_port);
    ret = inet_pton(AF_INET, output_ip, &(context_data->socket_addr->sin_addr));
    if(0 == ret) {
        printf("inet_pton fail!\n");
        return NULL;
    }
    
    ret = setsockopt(context_data->socket, IPPROTO_IP, IP_MULTICAST_TTL,
                        &option_ttl, sizeof(int));
    if(ret < 0) {
        printf("ttl configuration fail!\n");
        return NULL;
    }
    
    ret = setsockopt(context_data->socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
    if(ret < 0) {
        printf("resue configuration fail!\n");
        return NULL;
    }   
    

    That is the code to send UDP packet:

    int send_size = sendto(context_data->socket, buf, buf_size, 0,
                          (struct sockaddr *)context_data->socket_addr, sizeof(*context_data->socket_addr)));
    //the video or audio data is in buf and its size is buf_size.
    

    That is the code I used to get the sending buffer size:

    int bufsize; 
    int size = sizeof(bufsize);
    getsockopt(context_data->socket,SOL_SOCKET, SO_SNDBUF, &bufsize, &size);
    

    That is the code I used to configure the sending buffer size:

    tmp = 200000;
    ret = setsockopt(context_data->socket, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp));
    if(ret < 0) {
        printf("sending buffer size configuration fail!\n");
        return NULL;
    }