user3696412 user3696412 - 6 months ago 26
Python Question

Relay between two sockets, interrupt to plug in own commands

I have a Programm A talking to machine B over a tcp socket. Now I have my own application C that needs to talk to B every once in a while as well. So I want C to relay all communication between A and B bidirecionally. As soon as C has to talk to B, the relaying shall be stopped, the socket to B should be flushed / emtpied of all waiting data and C should talk to B, receive what it needs, and then the relaying between A and B should start again.

I'm pretty new to sockets in Python so I only know some basic commands and need some pointing in the right direction to know what to read and what to watch out for (or a fully worked example, if someone happens to have done something like that already).

Since the relaying should run in the background while C is doing other stuff than talking to B, I also wonder wheather I should use threads to this or if there is a better alternative (in the question referenced below, asynchronus is used)?

I also found this question Need help creating a TCP relay between two sockets and as far as I understand it, the relaying part should be similiar to my question, but I can't really discern where the relay is done.


Ok, I figured it out. Here is my solution, implemented in a class to control the machine:

import struct
import socket
import time
import threading
    from configparser import ConfigParser
except ImportError:
    from ConfigParser import ConfigParser  # ver. < 3.0

class machineClass():
    def __init__(self):
        self.read_config() # gets IP's and Ports for machine and relay socket and stores them in self.machineIP, self.machinePort, self.relayIP and self.relayPort
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.connect((self.machineIP, self.machinePort))

        self.stopRelayEvent = threading.Event()
        self.relayStoppedEvent = threading.Event()

        relaySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        relayThread = threading.Thread(target=self.relay, args=(relaySocket,self.s,self.stopRelayEvent,self.relayStoppedEvent))


        print(" Machine [connected]")

    def relay(self,relaySocket,machineSocket,stopRelayEvent,relayStoppedEvent):
        while 1:
            if not relayStoppedEvent.isSet():
            relaySocket.listen(1) # waits for connection from software **B**, in loop because **B** reconnects every now and then. While waiting, connection is not blocked for **C** because relayStoppedEvent is set.
            relayCon, relayAddr = relaySocket.accept()
            print('Connected with Software **B** on ' + relayAddr[0] + ':' + str(relayAddr[1]))

            while 1:
                if not stopRelayEvent.isSet():
                    if relayStoppedEvent.isSet():
                    data = relayCon.recv(84)
                    if len(data) == 0:
                        break # in case connection is lost, break loop and go back to waiting for new connection.
                    data = relayCon.recv(84)    

    def sendDataToMachine(self,data): # Function for **C** to send data to machine **B**
        return_data = self.s.recv(84)
        return return_data