c++socketsudpsendto

Sending UDP packets via sendto


I want to send a datagram UDP message via sendto with 4-byte address, 1 short int number, and 4 bytes int distance. So it should be exactly 9-bytes. How can i do it? I already have tried to convert those values and put them in buffer, but it didn't work.

sendto(sockfd, &message, sizeof(message), 0, (struct sockaddr*) &server_address, sizeof(server_address));

EDIT: i also tried to create, but it has 12 bytes.

 struct msg {
      uint32_t dist;
      uint8_t num ;
       struct in_addr addr;
  
};

Solution

  • The most portable way is to assemble the bytes into a buffer yourself:

    uint8_t buf[64];  // make sure this is large enough to hold the bytes
    uint8_t * b = buf;
    
    uint32_t neDist = htonl(msg.dist);   // send multi-byte values in big-endian form
    memcpy(b, &neDist, sizeof(neDist));
    b += sizeof(neDist);
    
    memcpy(b, &msg.num, sizeof(msg.num));
    b += sizeof(msg.num);
    
    uint32_t neAddr = htonl(msg.addr.s_addr);
    memcpy(b, &neAddr, sizeof(neAddr));
    b += sizeof(neAddr);
    
    uint32_t numBytesToSend = (b-buf);
    sendto(sockfd, buf, numBytesToSend, 0, (struct sockaddr*) &server_address, sizeof(server_address));
    

    ... and then on the receiving side, something like:

    uint8_t buf[64];  // make sure this is large enough to hold the bytes
    int32_t numBytesReceived = recvfrom(sockfd, buf, sizeof(buf), ...);
    if (numBytesReceived > 0)
    {
        struct msg m;
    
        uint8_t * b = buf;
        uint8_t * fib = buf+numBytesReceived;  // pointer to the first invalid byte
    
        if ((fib-b) >= sizeof(m.dist))
        {
           uint32_t neDist;
           memcpy(&neDist, b, sizeof(neDist));
           b += sizeof(neDist);
           m.dist = ntohl(neDist);  // convert from big-endian back to local-endian
    
           if ((fib-b) >= sizeof(m.num))
           {
              memcpy(&m.num, b, sizeof(m.num));
              b += sizeof(m.num);
    
              if ((fib-b) >= sizeof(m.addr.s_addr))
              {
                 uint32 neAddr;
                 memcpy(&neAddr, b, sizeof(neAddr));
                 m.addr.s_addr = ntohl(neAddr);
    
                 printf("At this point, (m) is fully populated and ready for use\n");
              }
           }
        }
    }