Многопроцессорное соединение двух процессов одновременно с TCP - PullRequest
1 голос
/ 25 марта 2019

Я новичок в программировании на Python и пытаюсь научиться многопроцессорному решению проблемы, с которой я столкнулся.

У меня есть проект с Raspberry Pi (Linux) и с другого ПК / устройства (Windows), я пытаюсь обмениваться данными между ними с помощью TCP-соединения. Я сделал работающий код сервер / клиент (сервер на малине и клиент на ПК).

Следующим шагом является создание визуального приложения (в данном случае я выбираю для этого kivy) и напрямую подключаем и отправляем данные с моего компьютера на мой raspberry с помощью этого приложения, при этом ПК является клиентом здесь непосредственно из кода python / kivy.

Проблемы заключаются в том, что когда я подключаюсь, вводя IP и PORT в моем приложении kivy, сценарий соединяет меня, но немедленно убивает сервер, и я хочу, чтобы мой сервер постоянно работал постоянно.

Другая проблема, представьте, что сервер не уничтожен кодом, в другой функции с именем send_data я хочу отправить переменную скорости и угла на мой сервер и все еще быть подключенной к серверу, и сервер будет жив, ТАК мой единственный вариант был многопроцессорным.

Код для сервера на малине:

import socket

host = ''
port = int(input("Port: "))

speed = []
angle = []

def setupServer():
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   print ("Socket created")
   try:
      s.bind((host, port))
   except socket.error as msg:
      print(msg)
   print("Socket bind complete.")
   return s

def setupConnection():
   s.listen(1)
   conn, address = s.accept()
   print("Connected to: " +address[0] + ":" + str(address[1]))
   return conn

def dataTransfer(conn):
   global speed,angle

   data = conn.recv(1024)
   data = data.decode('utf-8')
   """ split the data """
   dataMessage = data.split(' ',1)
   speed = dataMessage[0]
   angle = dataMessage[1]

   print(speed)
   print(angle)

   if dataMessage[0] == 'exit':
       print("Client has left the server")
       break
   if dataMessage[0] == 'kill':
       print("Server is shutting down")
       s.close()
       break

   conn.close()


s = setupServer()

while True:
   try:
      conn = setupConnection()
      dataTransfer(conn)
   except:
      break

Код для моего клиента с модулем kivy:

import kivy
import socket
import multiprocessing

kivy.require('1.10.1')

from kivy.app import App
from kivy.uix.button import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.config import Config
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty


Config.set('graphics', 'width', '400')
Config.set('graphics', 'height', '400')


class MyGrid(Widget):
    ip = ObjectProperty(None)
    port = ObjectProperty(None)
    speed = ObjectProperty(None)
    angle = ObjectProperty(None)

    def connecting(self):
        h = self.ip.text
        p = int(self.port.text)

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((h, p))
        self.lbl.text = "Connected to server!"

        return s

    def __init__(self):
        super(MyGrid, self).__init__()

    def send_data(self):
        h = self.ip.text
        p = int(self.port.text)
        speed = self.speed.text
        angle = self.angle.text

        s = MyGrid.connecting(h, p)

        var = speed + " " + angle
        s.send(str.encode(str(var)))

        #reply = s.recv(1024)
        #print(reply.decode('utf-8'))
        self.lbl.text = "Speed and angle has been send!"

        s.close()

    def dct(self):
        h = self.ip.text
        p = int(self.port.text)

        s = MyGrid.connecting(h, p)
        s.close()
        self.lbl.text = "Client disconnected!"

    def stop_srvv(self):
        h = self.ip.text
        p = int(self.port.text)

        s = MyGrid.connecting(h, p)

        s.send(str.encode(str("kill ")))

        reply = s.recv(1024)
        print(reply.decode('utf-8'))
        self.lbl.text = "Server stopped!"


class MyApp(App):
    def build(self):
        return MyGrid()


if __name__ == "__main__":
    MyApp().run()

Код для части оформления kivy:

<MyGrid>
    lbl: my_label
    ip: ip
    port: port
    speed: speed
    angle: angle

    GridLayout:
        cols: 1
        size: root.width, root.height

        GridLayout:
            cols: 2
            Label:
                text: "IP"

            TextInput:
                id: ip
                multiline: False

            Label:
                text: "PORT"

            TextInput:
                id: port
                multiline: False

            Label:
                text: "Speed"

            TextInput:
                id: speed
                multiline: False

            Label:
                text: "Angle"

            TextInput:
                id: angle
                multiline: False

        GridLayout:
            cols: 2
            Button:
                text: "CONNECT"
                on_press: root.connecting()

            Button:
                text: "DISCONNECT"
                on_press: root.dct()

        GridLayout:
            cols: 2

            Button:
                text: "SEND DATA"
                on_press: root.send_data()

            Button:
                text: "STOP SERVER"
                on_press: root.stop_srvv()

            Label:
                id: my_label
                text: ""

Я хочу подключаться, отключаться и отправлять данные через TCP-соединение, все они с сервером все время активны (сервер должен закрываться ТОЛЬКО при нажатии кнопки «Остановить сервер»). Очевидно, модуль kivy имеет странную структуру, и я не совсем понимаю, как назначить многопроцессорность в моей задаче И структуре kivy.

Может кто-нибудь из вас, ребята, взглянет на мой код и исправит его с помощью многопроцессорной обработки, чтобы сделать то, что мне нужно, или, по крайней мере, дать мне совет / учебник или что-то в этом роде?

ОБНОВЛЕНИЕ : я еще не использовал многопроцессорный код, как вы видите, во-первых, я попытался с помощью пула и карты разделить соединительную часть на одно ядро, а остальные - на другое, но сохранить сервер жив, мне нужна последовательность петель в соединительной зоне. (у моего ноутбука только 2 ядра)

1 Ответ

0 голосов
/ 25 марта 2019

Используйте threading . Многопроцессорная обработка - это все равно, что запускать совсем другой процесс, и обмен данными будет нелегким, если вы не будете записывать в файлы. Благодаря многопоточности вы находитесь в одном процессе и можете обращаться к переменным между нитями.
Вот небольшой пример того, как реализовать многопоточность.

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
import threading

sock = socket.socket()
sock.connect((host, port))


KV = """

BoxLayout:
    Label:
        text: app.label_text

"""

class MyApp(App):
    label_text = StringProperty("")

    def build(self):
        threading.Thread(target=self.update_label).start()
        return Builder.load_string(KV)


    def update_label(self):
        while True:
            self.label_text = sock.recv(1025)


MyApp().run()
...