Socket messages from Python to JUCE

I want to open a JUCE C++ program using subprocess in Python. The Python program already exists and does this with another Python program, but I want to update it to use JUCE.

I can send from JUCE and receive it in Python. I cannot send from Python and receive it in JUCE.
I use:

msg = sock.recv(4)
sock.send(msg)

Hoping it will just copy the magic number for now, until I figure out why it doesn’t work. But I also tried sending the magic number manually, no luck.
messageReceived is never called.
Please, why are the messages not received by the JUCE InterProcessConnection and sent to messageReceived?

Python server:

import threading
import subprocess
import socket
import queue
import time
import sys
import chardet

cbport = 5899
active = 1

def waitforconnect(sock, q):
    print("waiting...")
    conn = sock.accept()
    print("Wow!")
    q.put(conn)

def delegatecallbacks(sock):
    active = 1
    cbtext = "."
    print("delegating...")
    while active == 1:
        time.sleep(0.2)
        try:
#            print(sock.recv(1))
            msg = sock.recv(4)
            sock.send(msg)
            time.sleep(0.1)
            if msg:
                sock.send(msg)
                enc = chardet.detect(msg)["encoding"]
#            print("enc ", enc)
#            if msg:
#                dec = msg.decode()
                hx = [hex(i) for i in list(msg)]
                if enc == "ascii":
                    cbtext = msg.decode(enc)
                    print(enc, hx, cbtext)
                else:
                    print(enc, hx)
#            while cbtext.count('CB'):
#                cb, cbtext = cbtext.split('CB', 1)

        except:
                print("Callback Socket Unavailable:", sys.exc_info()[0])
#                print sock
                pass



def launch():
    cbport = 5899
    #create socket to receive callbacks to move the time cursor
    cbwait = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#    cbwait.settimeout(4.0)
    count = 0
    while count < 30000:
        try:
            cbwait.bind(("127.0.0.1", cbport))
            print('Callback Port: %s' % str(cbport))
            break
        except:
            cbport += 1
            count += 1
            if count == 30000:
                print("NO PORTS AVAILABLE FOR CALLBACK")
                active = 0

    cbwait.listen(2)

        #thread to wait for ratengine to connect
    q = queue.Queue()
    wait = threading.Thread(target=waitforconnect, args=(cbwait, q)) # 
    wait.start()

    count = 0

#    try:
#        rau = subprocess.Popen((r'C:\Users\Charlie\Documents\CSHJr2021\Coding\rationale-2020\RatEngine\Builds\VisualStudio2019\x64\Debug\ConsoleApp\RatEngine.exe', str(cbport)))
#    except:
#        print("Engine stolen")
#        active = 0

    wait.join()
    print("joined")
    cbsock = q.get()[0]

    threading.Thread(target=delegatecallbacks, args=(cbsock,)).start()
    time.sleep(60)

    try:
        cbsock.sendall('HelloRATENDMESSAGE')
    except:
        print("Unable to start")

Main.cpp:

/*
  ==============================================================================

    This file contains the basic startup code for a JUCE application.

  ==============================================================================
*/

#include <JuceHeader.h>
#include "RatEngine.h"
//==============================================================================
int main (int argc, char* argv[])
{
    int portno;
    //portno = int(argv[1]);

    RatEngine ratEngine(5899);
    // ..your code goes here!
    ratEngine.endItAll();
    return 0;
}

RatEngine.h:

/*
  ==============================================================================

    RatEngine.h
    Created: 11 Feb 2022 2:06:16am
    Author:  Home

  ==============================================================================
*/

#pragma once
#include <JuceHeader.h>
class RatEngine : public juce::InterprocessConnection
{
public:
    RatEngine(int);
    ~RatEngine();
    void messageReceived(const MemoryBlock& message) override;
    void connectionMade() override;
    void connectionLost() override;
    void endItAll();
//    void timerCallback();

private:
    int cbport;
    bool active = true;
};

RatEngine.cpp:

/*
  ==============================================================================

    RatEngine.cpp
    Created: 11 Feb 2022 2:06:39am
    Author:  Home

  ==============================================================================
*/

#include "RatEngine.h"
#include <string>
#include <iostream>
//#include <chrono>
//#include <thread>

RatEngine::RatEngine(int portno) {
    cbport = portno;
    connectToSocket("127.0.0.1", cbport, 10000);
    std::string mystr = "Hello World!";
    bool sent;
    for (int r = 0; r < 4; r++) {
        MemoryBlock myMessage;
        myMessage.setSize(12);
        for (int i = 0; i < 12; i++) {
            myMessage[i] = mystr[i];
        }
        sent = sendMessage(myMessage);
    }
    int g;
    std::cin >> g;
    //startTimer(100000);
//    std::function<void()> endItAll = [&]() {this->active = false; };
//    while (active) {
//        callAfterDelay(100000, endItAll);
//    }
}


void RatEngine::endItAll() {
    //active = false;
    int g;
    std::cin >> g;
}

RatEngine::~RatEngine() {
    disconnect();
}

void RatEngine::messageReceived(const juce::MemoryBlock &msg) 
{
    juce::MemoryBlock checker = msg;
    int a = 0;
    std::cin >> a;
}

void RatEngine::connectionMade()
{

}

void RatEngine::connectionLost()
{

}

PS
For now, I am launching them separately. I run the Python program, debug RatEngine.exe (with a breakpoint before connecting), and run launch() manually in Python.

My attempts to send the magic number from Python are getting mangled.
I send:
0x2c9eb4f2
and JUCE sees:
0x63327830
For the message size, I send:
0x00000001
and JUCE sees:
0x34626539

What could possibly make that happen? Windows 10 x64…
Seems bizarre that an interprocess communication interface would have the “feature” of sending something other than what you tell it to send.
BTW I’m sending these as Python byte arrays:
send(b’0x2c9eb4f2’)

Well, so this part was a Python peculiarity, as I suspected. It’s the way Python writes hex bytes. It must be:
b’\x2c\x9e\xb4\xf2’

That gets JUCE past the magic number check in readNextMessage.
For some reason, though, JUCE is still not calling messageReceived after it passes this check. The magic number and message size are being read correctly. What gives??

I’ve got it, but there’s still something I don’t understand.

I was sending the magic number OK, but had the size (1) reversed, so the program was blocked waiting for more. I reversed the bytes of the message size and it checks out. But it STILL doesn’t call messageReceived unless callbacksOnMessageThread is false. If callbacksOnMessageThread is true, my messageReceived is not called at all. I mean, it’s a little confusing debugging the threads and checking that, but when it is set to FALSE, my messageReceived, which mirrors the message back to the sender, does send it back; when it is set to TRUE, the sender does not receive the message back.

So it appears that messageReceived is not called at all if callbacksOnMessageThread is true.

My intention here is for JUCE to be sending MIDI clock messages and other high-speed timing info. Is setting callbacksOnMessageThread to false going to present problems with something like that?

I test here and messageReceived is not called regardless of callbacksOnMessageThread is true or false. For the moment I could only use a shared file for the connection.