After having seen all beginners tutorials and hours of testing, I finally made it work. Maybe this is of use for another beginner...
My flow simulates a client sending requests to a TCP-Server A, which buffers the requests to send them one by one to another TCP-Server B, which processes them, then responds back to TCP-Server A, which then in turn responds to the client.
Thanks a lot for your efforts!
Still I can't attach files here, thus as JSON
[
{
"id": "e4027f0dc4b50d08",
"type": "comment",
"z": "7e7c311a0f8dcf81",
"name": "Emulating Client <-> TCP-Server <-> TCP-Server communication",
"info": "# Emulating Client <-> TCP-Server <-> TCP-Server communication\nThis flow emulates a client sending messages which will be buffered on a TCP-Server, sent one by one to another TCP-Server, that processes the requests.",
"x": 710,
"y": 80,
"wires": []
},
{
"id": "145298825c41ffb1",
"type": "group",
"z": "7e7c311a0f8dcf81",
"name": "Init",
"style": {
"fill": "#d1d1d1",
"label": true,
"color": "#000000"
},
"nodes": [
"c8690eda7fbf3016",
"d1175fcf1b66c758"
],
"x": 14,
"y": 39,
"w": 432,
"h": 82
},
{
"id": "c8690eda7fbf3016",
"type": "function",
"z": "7e7c311a0f8dcf81",
"g": "145298825c41ffb1",
"name": "INIT",
"func": "flow.set(\"queue\", []);\nflow.set(\"flowcounter\", 0);\n\nnode.warn(\"QUEUE LENGTH:\" + flow.get(\"queue\").length + \" | FLOWCOUNTER: \"+ flow.get(\"flowcounter\"));\nflow.set(\"busy\",false);\n",
"outputs": 0,
"timeout": 0,
"noerr": 0,
"initialize": "flow.set(\"queue\", []);\nflow.set(\"flowcounter\", 0);\n\nnode.warn(\"QUEUE LENGTH:\" + flow.get(\"queue\").length + \" | FLOWCOUNTER: \" + flow.get(\"flowcounter\"));\nflow.set(\"busy\", false);\n",
"finalize": "flow.set(\"queue\", []);\nflow.set(\"flowcounter\", 0);\n\nnode.warn(\"QUEUE LENGTH:\" + flow.get(\"queue\").length + \" | FLOWCOUNTER: \" + flow.get(\"flowcounter\"));\nflow.set(\"busy\", false);\n",
"libs": [],
"x": 370,
"y": 80,
"wires": []
},
{
"id": "d1175fcf1b66c758",
"type": "inject",
"z": "7e7c311a0f8dcf81",
"g": "145298825c41ffb1",
"name": "RESET Queue and counter",
"props": [],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 180,
"y": 80,
"wires": [
[
"c8690eda7fbf3016"
]
]
},
{
"id": "b75b905e614281d1",
"type": "group",
"z": "7e7c311a0f8dcf81",
"name": "EMULATOR Client (or whatever sends TCP-Requests)",
"style": {
"fill": "#c8e7a7",
"label": true,
"color": "#000000"
},
"nodes": [
"b89748ba450ac707",
"adfd8738a2d7cae8",
"0bf3b0e9c8dda88d",
"bed3f8ec500ce25b",
"7c5c08a91e8ade63",
"c19a519b27b7f1d2",
"75cf2e5b421eb801",
"22c2c6698bc32648",
"045e6c2224c07783",
"62d0441961851971"
],
"x": 14,
"y": 139,
"w": 1412,
"h": 122
},
{
"id": "b89748ba450ac707",
"type": "inject",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"type\":\"request\",\"state\":\"unprocessed\"}",
"payloadType": "json",
"x": 110,
"y": 220,
"wires": [
[
"bed3f8ec500ce25b"
]
]
},
{
"id": "adfd8738a2d7cae8",
"type": "debug",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "Server request",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 620,
"y": 180,
"wires": []
},
{
"id": "0bf3b0e9c8dda88d",
"type": "function",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "AddCounter",
"func": "let counter = flow.get(\"flowcounter\");\nmsg.payload.flowcounter = counter;\ncounter = counter + 1;\nflow.set(\"flowcounter\",counter);\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 430,
"y": 220,
"wires": [
[
"adfd8738a2d7cae8",
"75cf2e5b421eb801"
]
]
},
{
"id": "bed3f8ec500ce25b",
"type": "function",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "CreateGUID",
"func": "function generateGUID() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n// Ensure msg.payload is an object (if it’s not already)\nif (typeof msg.payload !== 'object' || msg.payload === null) {\n msg.payload = {}; // Initialize as an empty object if needed\n}\n\n// Generate a GUID and add it to msg.payload\nmsg.payload.guid = generateGUID();\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 270,
"y": 220,
"wires": [
[
"0bf3b0e9c8dda88d"
]
]
},
{
"id": "7c5c08a91e8ade63",
"type": "debug",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "FINALLY",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1320,
"y": 220,
"wires": []
},
{
"id": "c19a519b27b7f1d2",
"type": "complete",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "",
"scope": [
"daef06209d72aad1"
],
"uncaught": false,
"x": 1050,
"y": 220,
"wires": [
[
"045e6c2224c07783"
]
]
},
{
"id": "75cf2e5b421eb801",
"type": "json",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "toString",
"property": "payload",
"action": "str",
"pretty": false,
"x": 600,
"y": 220,
"wires": [
[
"22c2c6698bc32648"
]
]
},
{
"id": "22c2c6698bc32648",
"type": "tcp out",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "",
"host": "127.0.0.1",
"port": "62000",
"beserver": "client",
"base64": false,
"end": true,
"tls": "",
"x": 820,
"y": 220,
"wires": []
},
{
"id": "045e6c2224c07783",
"type": "json",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 1190,
"y": 220,
"wires": [
[
"7c5c08a91e8ade63"
]
]
},
{
"id": "62d0441961851971",
"type": "comment",
"z": "7e7c311a0f8dcf81",
"g": "b75b905e614281d1",
"name": "Inject messages here. Fast!",
"info": "",
"x": 160,
"y": 180,
"wires": []
},
{
"id": "2885526795da429b",
"type": "group",
"z": "7e7c311a0f8dcf81",
"name": "TCP-Server: Watchdog with Message Buffer",
"style": {
"fill": "#ffefbf",
"label": true,
"color": "#000000"
},
"nodes": [
"ac777e3562cebd25",
"95a07b23231f73c8",
"419ca868a9a718a5",
"daef06209d72aad1",
"4115a1eef647ae8c",
"421bd258294fc1a5",
"1b3ab7efb687435d",
"9ebded45a59bb4e3",
"71056ad2ce2bc309",
"469c639ce9a8e9b0",
"89b15622b8ceb350",
"5a3aaa8423c8fe72"
],
"x": 14,
"y": 279,
"w": 1412,
"h": 262
},
{
"id": "ac777e3562cebd25",
"type": "tcp in",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "Watchdog In @ TCP 62000",
"server": "server",
"host": "",
"port": "62000",
"datamode": "single",
"datatype": "utf8",
"newline": "",
"topic": "Watchdog In",
"trim": false,
"base64": false,
"tls": "",
"x": 150,
"y": 440,
"wires": [
[
"9ebded45a59bb4e3",
"71056ad2ce2bc309"
]
]
},
{
"id": "95a07b23231f73c8",
"type": "tcp request",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "Request Unreal @ TCP 63000",
"server": "127.0.0.1",
"port": "63000",
"out": "time",
"ret": "buffer",
"splitc": "100",
"newline": "",
"trim": false,
"tls": "",
"x": 850,
"y": 440,
"wires": [
[
"89b15622b8ceb350",
"daef06209d72aad1",
"1b3ab7efb687435d"
]
],
"info": "Request to Unreal"
},
{
"id": "419ca868a9a718a5",
"type": "debug",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "Watchdog 62000 Out",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1280,
"y": 480,
"wires": []
},
{
"id": "daef06209d72aad1",
"type": "tcp out",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "TCPWatchDogDone",
"host": "",
"port": "",
"beserver": "reply",
"base64": false,
"end": false,
"tls": "",
"x": 1160,
"y": 420,
"wires": []
},
{
"id": "4115a1eef647ae8c",
"type": "debug",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "Watchdog 62000 from Queue",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 680,
"y": 500,
"wires": []
},
{
"id": "421bd258294fc1a5",
"type": "function",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "AddToQueue",
"func": "var queue = flow.get('queue') || [];\nvar busy = flow.get('busy') || false;\n\nqueue.push(msg);\nflow.set('queue', queue);\n\nnode.log(\"queue busy: \" + busy + \" | Adding msg with id \" + msg.payload.guid + \" counter: \" + msg.payload.flowcounter + \", queue length after push: \" + queue.length);\n\n\nvar busy = flow.get('busy') || false;\n\nif (!busy && queue.length > 0) {\n // If Unreal is not busy, send the first message from the queue\n\n var nextMsg = queue.shift(); // Take the first message off the queue\n\n// node.warn(\"Unreal not busy, shifting, current queue length after shifting: \" + queue.length);\n flow.set('queue', queue); // Update the queue in context\n flow.set('busy', true); // Mark Unreal as busy\n\n\n\n return nextMsg; // Return the message to be sent to the next node (TCP)\n}\n//node.warn(\"Unreal is busy, doing nothing, so current queue length is: \" + queue.length);\n\n\nreturn null; // Unreal is busy, don't send anything yet\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 470,
"y": 440,
"wires": [
[
"4115a1eef647ae8c",
"469c639ce9a8e9b0"
]
]
},
{
"id": "1b3ab7efb687435d",
"type": "function",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "Acknowledge ready state",
"func": "\nvar queue = flow.get('queue') || [];\nnode.log(\"Acknowleding reponse from UE | Queue busy before check: \" + flow.get('busy') + \" | Queue length before check: \" + queue.length);\n\n// Get the queue\nflow.set('busy', false);\n\n// Log the current length of the queue to the console\n\n// If there are messages in the queue, send the next one\nif (queue.length > 0) {\n var nextMsg = queue.shift(); // Remove the first message from the queue\n node.log(\"Sending next msg with guid \" + nextMsg.payload.guid + \" counter: \" + nextMsg.payload.flowcounter + \" | queue length after sending: \" + queue.length); \n flow.set('queue', queue); // Update the queue in context\n flow.set('busy', true); // Mark Unreal as busy again\n// node.warn(\"Current queue length after acknowledgment: \" + queue.length);\n return nextMsg; // Return the next message to be sent to the TCP Out Node\n}\nelse\n node.error(\"LAST MESSAGE IN QUEUE SENT - QUEUE EMPTY\");\n\n\nreturn null; // No more messages in the queue",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 770,
"y": 360,
"wires": [
[
"469c639ce9a8e9b0"
]
]
},
{
"id": "9ebded45a59bb4e3",
"type": "debug",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "Watchdog 62000 In",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 370,
"y": 500,
"wires": []
},
{
"id": "71056ad2ce2bc309",
"type": "json",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 330,
"y": 440,
"wires": [
[
"421bd258294fc1a5"
]
]
},
{
"id": "469c639ce9a8e9b0",
"type": "json",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 650,
"y": 440,
"wires": [
[
"95a07b23231f73c8"
]
]
},
{
"id": "89b15622b8ceb350",
"type": "json",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 1110,
"y": 480,
"wires": [
[
"419ca868a9a718a5"
]
]
},
{
"id": "5a3aaa8423c8fe72",
"type": "comment",
"z": "7e7c311a0f8dcf81",
"g": "2885526795da429b",
"name": "After a message is done, check if more messages are waiting.",
"info": "",
"x": 880,
"y": 320,
"wires": []
},
{
"id": "a2cddeeeb6df5b61",
"type": "group",
"z": "7e7c311a0f8dcf81",
"name": "TCP-Server processing the requests one by one.",
"style": {
"label": true,
"color": "#000000",
"fill": "#bfdbef"
},
"nodes": [
"8eedbd8a913e3510",
"402456a02fe1a44f",
"965b1a7cef34608b",
"f5c99c38afb98aff",
"249b754e2c1ea840",
"ba3e2ece5869de2d",
"a2efcb6aaf8b2059",
"3d6ef7bc87a4e063",
"e6cedb24e5d21c7c"
],
"x": 14,
"y": 579,
"w": 1272,
"h": 162
},
{
"id": "8eedbd8a913e3510",
"type": "tcp in",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "UNREAL Server TCP 63000",
"server": "server",
"host": "",
"port": "63000",
"datamode": "stream",
"datatype": "buffer",
"newline": "",
"topic": "",
"trim": false,
"base64": false,
"tls": "",
"x": 160,
"y": 660,
"wires": [
[
"ba3e2ece5869de2d"
]
]
},
{
"id": "402456a02fe1a44f",
"type": "debug",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "UE 63000 In",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 510,
"y": 700,
"wires": []
},
{
"id": "965b1a7cef34608b",
"type": "tcp out",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "UNREAL Out @ TCP 63000",
"host": "",
"port": "",
"beserver": "reply",
"base64": false,
"end": false,
"tls": "",
"x": 1140,
"y": 660,
"wires": []
},
{
"id": "f5c99c38afb98aff",
"type": "delay",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "Simulate workload time",
"pauseType": "delay",
"timeout": "3",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 750,
"y": 660,
"wires": [
[
"3d6ef7bc87a4e063"
]
]
},
{
"id": "249b754e2c1ea840",
"type": "debug",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "UE 63000 out",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1100,
"y": 620,
"wires": []
},
{
"id": "ba3e2ece5869de2d",
"type": "json",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 350,
"y": 660,
"wires": [
[
"402456a02fe1a44f",
"a2efcb6aaf8b2059"
]
]
},
{
"id": "a2efcb6aaf8b2059",
"type": "function",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "set state processed",
"func": "msg.payload.state = \"processed\";\nreturn msg;\n\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 530,
"y": 660,
"wires": [
[
"f5c99c38afb98aff"
]
]
},
{
"id": "3d6ef7bc87a4e063",
"type": "json",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 930,
"y": 660,
"wires": [
[
"965b1a7cef34608b",
"249b754e2c1ea840"
]
]
},
{
"id": "e6cedb24e5d21c7c",
"type": "comment",
"z": "7e7c311a0f8dcf81",
"g": "a2cddeeeb6df5b61",
"name": "Set the message as being processed",
"info": "Set the message state to \"processed\"",
"x": 580,
"y": 620,
"wires": []
}
]