Python//C#--SOCKET Verbindung wird ständig unterbrochen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
raspberryPiBRA
User
Beiträge: 3
Registriert: Donnerstag 1. Februar 2018, 10:37

Hi Experten,


ich bin neu in die Programmierwelt eingestiegen und bin schon so weit, dass ich eine Socket-Verbindung mittels C# an einem Raspberry Pi(Python) erstellt habe.


Mit der Software wird ein Servomotor angesteuert. Nach einer weile unterbricht er jedoch die Verbindung und der Raspberry Pi sendet keine Befehle an dem Servomotor, weil ich glaube, dass die Socket Verbindung unterbrochen wurde.

Kennt jemand eine Lösung zu meinem Code?

Code: Alles auswählen

import socket
from Handler import Handler
import time
from Servo import Servo
def Server(serverSocket, port):
    handler = Handler(12, 50)        
    serverSocket.listen(1)
    i=0
    connect = 1
    try:
        while i == 0:
            clientSocket, addr = serverSocket.accept()
            i = 1
        while connect == 1: 
            data = clientSocket.recv(1024)
            request = handler.handleRequest(data)
            if not data:
                  break
            if request == "SSDN K0":        
                connect = 0
            
    except Exception as ex: 
        print(ex)
    
    Server(serverSocket, port)
    
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port=1234
serverSocket.bind(('192.168.0.8',port))
Server(serverSocket, port)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dein Code ist ziemlich verworren. Rekursion (also den Wiederaufruf von "Server") als Loesung um sich neu zu verbinden ist eine schlechte Idee, denn so sammelst langsam aber sicher einen grossen Stack auf, der dann irgendwann zum Absturz fuehrt.

Deine while i Schleife ist komplett nutzlos, da sie genau ein Statement genau einmal ausfuehrt. Die Benamung entspricht nicht PEP8, was fuer uns alte Hasen verwirrend ist. Damit machst du es uns also schwerer, dir zu helfen.

Dann gibt es ein inhaerentes Problem, das du selbst ohne Verbindungsabbrueche hast: du glaubst, du bekommst immer Nachrichten mit genau einem Befehl. So funktionieren Sockets aber nicht. Die stellen einen Datenstrom dar, und Bytes kommen da in beliebigen Quantitaeten rausgetroepfelt. Das funktioniert mal gut, aber wenn du den Router tauschst oder ueber ein anderes Netzwerk arbeitst, ist ploetzlich Sense. Da muss eigentlich ein Protokoll hin.

Last but not least: du faengst eine Exception, sagst uns aber nicht, wie die aussieht. Bitte poste die.

Ich wuerde dir raten, statt roher Sockets gleich eine Abstraktionsstufe mehr einzubauen, und auf eine Middleware wie nanomsg oder zeromq zu setzen. Damit erreichst du dein Ziel schneller und robuster, inklusive automatischer wiederaufnahme der Verbindung bei Abbruch. Ich mache das fuer meinen ferngesteuerten Roboter auch: https://github.com/deets/jetbot-3000/bl ... se.py#L109
raspberryPiBRA
User
Beiträge: 3
Registriert: Donnerstag 1. Februar 2018, 10:37

__deets__ hat geschrieben:Dein Code ist ziemlich verworren. Rekursion (also den Wiederaufruf von "Server") als Loesung um sich neu zu verbinden ist eine schlechte Idee, denn so sammelst langsam aber sicher einen grossen Stack auf, der dann irgendwann zum Absturz fuehrt.

Deine while i Schleife ist komplett nutzlos, da sie genau ein Statement genau einmal ausfuehrt.
Vielen Dank für deine ausführliche Nachricht. Ich bin grade dabei zu lernen, wie man die Exceptions ausliest. Ich werde dir die Exceptions zusenden, sobald ich sie habe.

Hast du eine bessere Idee, wie ich die von dir angesprochenen Fehler beseitige?
Benutzeravatar
noisefloor
User
Beiträge: 4172
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

exakt den gleichen Thread gibt's auch im Raspi-Forum: https://forum-raspberrypi.de/forum/thre ... erbrochen/

@raspberryPiBRA: fährst du generell so einen "Hosenträger+Gürtel" Einstellung oder möchtest du einfach nur möglichst viele Leute mit deinem Problem beschäftigen?

Gruß, noisefloor
raspberryPiBRA
User
Beiträge: 3
Registriert: Donnerstag 1. Februar 2018, 10:37

__deets__ hat geschrieben:
Ich wuerde dir raten, statt roher Sockets gleich eine Abstraktionsstufe mehr einzubauen, und auf eine Middleware wie nanomsg oder zeromq zu setzen. Damit erreichst du dein Ziel schneller und robuster, inklusive automatischer wiederaufnahme der Verbindung bei Abbruch. Ich mache das fuer meinen ferngesteuerten Roboter auch: https://github.com/deets/jetbot-3000/bl ... se.py#L109
Ich finde diesen Abschnitt sehr interessant. Vielen Dank!
Benutzeravatar
__blackjack__
User
Beiträge: 13998
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`Server()` ist eine Funktion und der Name sollte deshalb eine Tätigkeit beschreiben, also `serve()`. Die Funktion verwendet das Argument `port` nicht. Die Module `time` und `Servo` werden auch nirgends verwendet.

Das es offenbar zwei Module gibt in denen jeweils eine Klasse mit dem gleichen Namen stecken ist ein „code smell“. Das ist Python und nicht Java. Also nicht eine Klasse pro Modul.

`connect` ist überflüssig. Im Fall das gar keine Daten empfangen wurden, wird die Schleife mit ``break`` verlassen. Das kann man natürlich auch machen falls die Anfrage zum beenden kommt. Und ziemlich wahrscheinlich möchte man die Anfrage gar nicht erst behandeln falls gar keine Daten kamen, also die Verbindung auf der Gegenseite geschlossen wurde.

Bei der Fehlerbehandlung sollte man keine wichtigen Informationen verwerfen. Wenn man nichts anderes macht als den Fehler auszugeben, sollte da auch der Traceback dabei sein. Das erreicht man am einfachsten über `logging`.

Über ein benötigtes Protokoll wurde ja schon gesprochen. Man kann sich von Socket-Objekte ein Datei-Objekt geben lassen um einfache Protokolle mit festen Nachrichtengrössen oder zeilenbasierte Protokolle selber zu basteln. Zwischenstand, ungetestet, für Nachrichten die immer genau 1024 Bytes gross sind:

Code: Alles auswählen

import logging
import socket

from Handler import Handler

MESSAGE_SIZE = 1024


def serve(server_socket):
    while True:
        handler = Handler(12, 50)
        server_socket.listen(1)
        try:
            client_socket, _ = server_socket.accept()
            client = client_socket.makefile("r")
            while True:
                data = client.read(MESSAGE_SIZE)
                if (
                    len(data) < MESSAGE_SIZE
                    or handler.handle_request(data) == "SSDN K0"
                ):
                    break

        except Exception:
            logging.exception("something went wrong while serving a client")


def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(("192.168.0.8", 1234))
    serve(server_socket)


if __name__ == "__main__":
    main()
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Antworten