So both A and B are in my lan, but I want to be able to get them to communicate via the controller that is on the internet. So both A and B go through a bidirectional NAT. I'm not sure if I have a two way NAT, I deduced it from the fact that my code works if I move the controller to local network and it doesn't work if I move the controller over the internet.
In that case it's also important that loopback of the external IP is enabled on the router. Not all routers have this.
If you have a small webserver on your PC on port 80 and you redirect port 80 to that PC on the router, are you able to access EXTERNAL_IP:80 and get the website?
If that works... you can put the controller on the internet and test with two internal clients.
Otherwise you need to take a whole other approach (i.e. using internal IP addresses and internal port).
A and B need to send in a string "internal_IP:internal_port".
For the connector...
*) if both A and B have the same external IP, the connector can send "internal_IP_A:internal_port_A" to B and "internal_IP_B:internal_port_B" to A. Both should be able to communicate directly.
*) if external IP of A and B are different, the connector sends "external_IP_A:external_port_A" to B and "external_IP_B:external_port_B" to A. Both A and B send each other a packet. One packet will be dropped and the other will be passed. But after that, communication between A and B should work (if there is not a restrictive NAT).
So when A and B are on the same network, internal IP:Ports are used. When they are not, a hole is punched for communication.
If for testing that both A and B are on different networks, but they are really not... loopback should be enabled. Otherwise you really can't test this.