Проблемы с Telnetlib: многопоточность и Telnet не работают должным образом - PullRequest
0 голосов
/ 07 апреля 2019

У меня есть устройство, которое выводит строки на порт 3000 моего IP-адреса.Я пытаюсь создать сценарий, который будет принимать эту строку, вносить в нее изменения, чтобы другое устройство могло ее правильно прочитать, а затем выводить ее на порт, который прослушивает мое другое устройство.

Iпытались сделать это двумя способами: линейно, в котором и устройство вывода, и прослушивающее устройство находятся на одном и том же порту, и Parallel, в котором я использую threading, чтобы попытаться установить два открытых соединения telnet, одно на порт устройства выводаи один на порт прослушивания.Технически, любой из них был бы приемлем, но я бы определенно предпочел, чтобы параллельное решение работало, поскольку прослушивающее устройство отвечает выводом, когда строка либо принимается, либо отклоняется, и я бы не хотел проверять это.Параллельное решение использует модель производитель / потребитель, в которой поток производителя будет добавлять строки, полученные устройством вывода, в очередь, а поток потребителя будет извлекать строки из очереди, вносить соответствующие изменения и затем выводить их вустройство прослушивания на другом порту.

Параллельное решение:

import threading, telnetlib, hbconfig, time #hbconfig is a python file containing variables that are to be used by my code
try:
    import Queue
except:
    import queue as Queue
q = Queue.Queue(16)

class Listener:
    def __init__(self):
        time.sleep(1) 
    def run(self, lock):
        try:
            ltn = telnetlib.Telnet(hbconfig.IN_SERVER_ADDRESS, hbconfig.IN_PORT)
            global q
            while(True):
                curr_string = ltn.read_until(b'\n')
                curr_string.decode('utf-8')
                try:
                    lock.acquire()
                    q.put(curr_string)
                    print("Listener put {0} in Queue".format(curr_string))
                    print("Queue: {0}".format(q))
                    lock.release()
                    pass
                except:
                    print("Listener: Something went wrong...")
                    pass
                time.sleep(.5)
        except socket.timeout:
            pass

class Speaker:
    def __init__(self):
        time.sleep(1)
    def run(self, lock):
        try:
            stn = telnetlib.Telnet(hbconfig.OUT_SERVER_ADDRESS, hbconfig.OUT_PORT)
            global q
            while(True):
                if not q.empty():
                    try:
                        lock.acquire()
                        curr_string = q.get()
                        new_string = fixString(curr_string)
                        stn.write(new_string.encode('ascii') + b'\n')
                        print("Speaker writing {0} to stn".format(new_string))
                        lock.release()
                    except:
                        print("Speaker: Something went wrong...")
                        lock.release()
                        pass
                time.sleep(0.5)
        except socket.timeout:
            pass
def fixString():
    #Modify the string as needed

def main():
    try:
        lock = threading.Lock()
        q = Queue.Queue(16)
        l = Listener()
        s = Speaker()
        lt = threading.Thread(target=(l.run), args=(lock,))
        st = threading.Thread(target=(s.run), args=(lock,))
        lt.daemon = True
        st.daemon = True
        lt.start()
        st.start()
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        print("KeyboardInterrupt detected. Closing threads and ending program.")

if __name__ == '__main__':
    main()

Линейное решение:

import telnetlib, hbconfig, time
def main():
    try:
        tn = telnetlib.Telnet(hbconfig.IN_SERVER_ADDRESS, hbconfig.IN_PORT)
        while True:
            curr_string = tn.read_until(b'\n')
            curr_string.decode('utf-8')
            new_string = fixString(curr_string)
            try:
                tn.write(new_string.encode('ascii') + b'\n')
                print('Speaker wrote {0} to tn.'.format(new_string))
            except socket.timeout: #Ignore socket timeouts
                pass
            except:
                print('Speaker was unable to write {0} to tn.'.format(new_string))
                pass

    except KeyboardInterrupt: #Safely close telnet connection on KeyboardInterrupt
        print("KeyboardInterrupt detected. Closing telnet connection and ending execution...")
        tn.close()
        print("Close successful. Goodbye!")
    except Exception as e:
        print(e)


if __name__ == "__main__":
    main()

В параллельном решении изначально я не использовал блокировку.В этой итерации поток Listener, который извлек строку, выведенную первым устройством, и поместил ее в очередь.Однако поток Speaker, который должен был вытолкнуть строки из очереди, выполняет с ним функцию fixString и выводит ее в OUT_PORT.Тем не менее, Speaker, похоже, на самом деле ничего не делал.Он никогда не печатал никаких заявлений об успехе и не печатал никаких ошибок.Listener будет функционировать, как и ожидалось, но Speaker ничего не сделает.

После добавления блокировки я получу сообщение об ошибке:

    self._target(*self._args, **self._kwargs)
TypeError: run() argument after * must be an utterable, not _thread.lock

Я знаю, что это говорит о том, что kwargs должен быть итеративным, а не блокировкой, но я не уверен, как исправить это, ни как исправить исходное решение (которое было таким же, за исключением блокировки).

В линейном решении я получаю сообщение, которое просто говорит: telnet connection closed., и программа просто сразу завершается.Я не уверен в том, почему это произошло.

Любая и вся помощь будет принята с благодарностью, так как я работал над этим некоторое время!Заранее спасибо!

...