سؤال

In the another question a user provided a method to send data to QuartzComposer via UDP. It appears that QuartzComposer is very particular about the padding of byte data sent to it. In particular it requires that each character sent be preceded with "\0\0\0".

I was able to mock up a quick Python program to solve this problem:

from socket import *

PORT = 50000
N = 3.14159265358

# connect to Quartz Composer on localhost port 50000
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)

for c in str(N):
    out = out + '\0\0\0' + c
s.sendto(out, ('225.0.0.0', PORT))

The critical section which I need to implement in C++ is the bit which pads a floating point number. Here is a quick Python mock up of the critical section:

def padfloat(n):
    out = ''
    for c in str(n):
        out = out + '\0\0\0' + c
    return out

if __name__ == '__main__':
    print(padfloat(3.14159265358))

Admittedly, my C++ chops are not so tight but I was able to use boost to get UDP up and running and to send a single hard coded message "0.7":

//
// Working C++ to Quartz Network Test
// 

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::udp;

enum { max_length = 1024 };

int main(int argc, char* argv[])
{
  try
  {
boost::asio::io_service io_service;

udp::socket s(io_service, udp::endpoint(udp::v4(), 0));

udp::resolver resolver(io_service);
udp::resolver::query query(udp::v4(), "225.0.0.0", "50000");
udp::resolver::iterator iterator = resolver.resolve(query);

using namespace std; // For strlen.

// TODO: alter code to take in any number

for (;;) {
  std::cout << "Press Any Key to send 0.7: ";
  char request[max_length];
  std::cin.getline(request, max_length);
  // size_t request_length = strlen(request);
  char test [] = {0,0,0,'0',0,0,0,'.',0,0,0,'7','\0'};
  s.send_to(boost::asio::buffer(test, 12), *iterator);
  std::cout << "Sent\n";
}
  }
  catch (std::exception& e)
  {
std::cerr << "Exception: " << e.what() << "\n";
  }
  return 0;
}

The rather trivial problem I need help with is how to take in a floating point number and to properly format it as a char array to send out with all the "\0\0\0" padding properly prepended. I'm about to do something ugly, but if someone can point me to an elegant fix, I'd be quite happy to learn a bit.

هل كانت مفيدة؟

المحلول

I don't have a compiler handy, but this should be sufficient.

  1. We do the string conversion
  2. Create a buffer 4 times the size (plus 1 for the null termination), initialized to 0
  3. Copy in the string at every 4th position.

I am not sure if asio expects the null terminator to be part of its size, so I followed your example.

float float_value = 4.2f;
std::string str = boost::lexical_cast<std::string>(float_value);

std::vector<char> char_buff((str.size() * 4) + 1, 0);

for (size_t i = 0; i < str.size(); i++)
  char_buff[(i * 4) + 3] = str[i];

s.send_to(boost::asio::buffer(&char_buff[0], char_buff.size()), *iterator);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top