-2

I am working on a school project where I am communicating with an embedded chip via a short Python script that looks like this:

            send = ''
            receive = ''

            send = input()
            data = [int(send), int(2)]
            print(int(send).to_bytes(1, 'big'))

            encoded_data = struct.pack('>{}B'.format(len(data)), *data)
            print(encoded_data)
            s.send(encoded_data)

            sleep(0.1)
            receive = s.recv(1024).decode('UTF-8','ignore').strip()
            print(receive, end = '\n')

I would like to translate this code into C++ to use in a larger piece of software. I started using Winsock2 and I have managed to establish a TCP connection and send/ receive data, but it's all mumbo jumbo when receiving (expected), because I do none of the special pre- & post-processing that I did in Python, rather I am just:

void send_message(const char *payload) {
    send(socket, payload, strlen(payload), 0);
}

...

std::string receive() {
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));
    int n = recv(socket, buffer, 1024, 0);
    if (n < 0) {
        error("Lost connection");
    }
    return buffer;
}

For sending, as far as I understand, the Python script is taking the console input and converting it to integers (ASCII), then creating an array that has two elements: the message, and the integer 2, packing that into a structure, formatted as a big-endian unsigned chars. How exactly can I do the same in C++? Do I need to create space in memory and memcpy an identical C++ struct into it? How will I assure the endianess will be respected? Side note, this code will only run on a Windows 10 64-bit machine.

For receiving, I see that the bytes received are in UTF-8 format and then they are decoded. I am planning on adding Boost to this project so I can handle the UTF-8 strings in a very elegant manner. Is this a good idea?

Edit

I see now that UTF-8 is backwards-compatible with ASCII so there's no need to do anything special when receiving, maybe writing something to remove the leading and trailing spaces from the message, just like .strip().

Karl Knechtel
  • 56,349
  • 8
  • 83
  • 124
ACCazacu
  • 9
  • 4
  • Since Stack Overflow is not a code-writing service, we do not take code translation requests. Rather than showing us working code in a different language, you should *describe what the code needs to do explicitly*, what it actually does, and how that is different from the requirement. Python expertise is not helpful in writing the C++ code, and there is no reason why a specification cannot be given in English. Also, please try to [do appropriate research first](https://meta.stackoverflow.com/questions/261592) and ask *one question at a time*; this is not a discussion forum, either. – Karl Knechtel May 05 '22 at 14:11
  • It appears that your question is "how can I create a structure with specific contents?" Rather than trying to emulate the approach taken in a different language, ask the question directly: you need a `struct` that has specific members; and then you need to create an instance of the struct, and then you need the members of that struct to have specific values. I assume you know how to do those things? As for endianness, that is a separate research topic. – Karl Knechtel May 05 '22 at 14:14
  • "For receiving, I see that the bytes received are in UTF-8 format and then they are decoded." This makes absolutely no sense, since demonstrably the data that was sent *does not in any way represent text* (notice how the `send` input is converted to integer before use?). If you need to replace code *that was written by someone else*, then you should *ask the author* for questions about the intended behaviour of the code. From what I can tell, it is very poor Python code that takes a strange approach to the problem. (BTW: we don't call that thing an "array" in Python, but a "list".) – Karl Knechtel May 05 '22 at 14:16
  • @KarlKnechtel Thank you for your input. It is indeed not my code, but something someone provided to me from an employee from the company that created this embedded system and they did not provide any further information. My main problem is creating that `struct`, with those specific members (which just like you said, is not a problem), and making sure that the endianess is correct, when creating the `payload`, which I don't really understand how to do besides allocating a continous space in memory and then copyting byte by byte. – ACCazacu May 05 '22 at 14:25
  • Did you try putting, for example, `c struct endianness` into a search engine? When I do that, I get https://stackoverflow.com/questions/6732127/is-there-a-way-to-enforce-specific-endianness-for-a-c-or-c-struct as the second result. Does it help? The [first result](https://linoxide.com/system-endianness-structure-padding-c-examples/) I get is off site, but also talks about structure padding. – Karl Knechtel May 05 '22 at 14:26
  • Note: rather than `char buffer[1024]; memset(buffer, 0, sizeof(buffer));`, you can `char buffer[1024] = {0};`, set the first byte to 0 (or whatever number you put in the braces) and then zero the rest of the array. Same runtime effect, but less code. That said, this is wasted time. `recv` told you where to place the terminating null with `n`, assuming `n` isn't negative (error) or zero (closed connection). – user4581301 May 05 '22 at 15:32
  • 1
    Other thigs to watch out for: If `recv` gets exactly 1024 characters, there is no room to place the null and buffer overflows suck, so ask for 1023 (`int n = recv(socket, buffer, sizeof(buffer) - 1, 0);`). Don't ignore `send`'s return code. It contains important status information like the actual number of bytes sent. This is you need to know. TCP/IP communications depend on correct handling of the diagnostics provided. – user4581301 May 05 '22 at 15:46
  • `recv` will gather whatever is available. You ask for 1024, but if only 123 bytes are available, you get 123 bytes. You might not get an entire message in one read and have to loop until all of the message arrives before you can interpret it. TCP is a stream. It doesn't care what your messages look like. If small messages are moving quickly and there's room to send more than one message in a packet, TCP will pack the suckers in, making it hard to tell them apart unless you have extra information in the communication protocol to make the message boundaries clear. – user4581301 May 05 '22 at 15:46
  • 1
    You can never count on TCP to keep your messages separated. TCP is designed to get data through even if the commies have nuked most of the infrastructure. It will buffer, fragment and do everything in its power to get the data through. If most of the packets go through the router on your desk, but one of them needs to go through Tibet, data will be buffered up waiting on that packet that went through Tibet, screwing up all of the careful timing you established to separate messages. – user4581301 May 05 '22 at 15:52

0 Answers0