Socket Connection Timeout

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Majanao
User
Beiträge: 5
Registriert: Donnerstag 5. Januar 2017, 13:35

Hallo zusammen,
ich bin schon eine Weile damit beschäftigt eine Netzwerkverbindung zwischen meinem Raspberry und meine PC aufzubauen.
Leider funktioniert das nicht so wie ich es will. Auf meinem Rechner starte ich den ThreadedServer und auf dem Pi den Client, der dann "Hallo Welt" senden soll.

Beide Geräte können sich gegenseitig anpingen aber, der Client stoppt bei sock.connect() schmeißt dann den timeout. Der Host wartet konstant auf eine Meldung des Clients bei sock.accept(). Das locale Netzwerk habe ich mit einem TPLinkWifi aufgebaut und den Port 1101 als Virtual Server geöffnet (auf jeden glaube ich das).

Habt ihr einen Tip für mich?

Code: Alles auswählen

import socket
import threading
from time import *


class ThreadedServer(object):
    def __init__(self, host=socket.gethostname(), port=1101):

        if host is None:
            self.host = socket.gethostname()
        else:
            self.host = host

        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind((self.host, self.port))

    def listen(self):
        self.sock.listen(5)
        while True:
            print("Waiting for client...")
            client, address = self.sock.accept()
            print ("Client %s gefunden mit der Adresse %s\n") % (client, adress)
            client.settimeout(60)
            threading.Thread(target=self.listenToClient, args=(client, address)).start()

    def listenToClient(self, client, address):

        print("Listener aktiviert fuer Server: %s\n") % socket.gethostname()

        size = 1024
        while True:
            try:
                data = client.recv(size)
                print(data)
                # if data:
                    # Todo: Daten handeln
                    # response = data
                    # client.send(response)

                # else:
                    # raise Exception('Client disconnected')
            except:
                client.close()
                return False


class Client(object):
    def __init__(self, host, port):

        self.host = host
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        print("Try to connect...")
        try:
            self.sock.connect((host, port))

        except socket.gaierror, e:
            print "Address-related error connecting to server: %s" % e
            sys.exit(1)
        except socket.error, e:
            print "Connection error: %s" % e
            sys.exit(1)
        print "Connected to %s" % host

    def connect(self, host, port):
        self.sock.connect((host, port))

    def send(self, data):
        totalsent = 0
        while totalsent < len(data):
            sent = self.sock.send(data[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent


if __name__ == "__main__":

    modus = "host"

    if modus == "host":
        ThreadedServer().listen()

    elif modus == "client":
        c = Client('192.168.0.100', 1101)

        while True:
            c.send("Hello World!")
            print("Daten gesendet")
            sleep(1)
Zuletzt geändert von Anonymous am Donnerstag 5. Januar 2017, 13:53, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Majanao: Funktioniert es denn wenn Client und Server auf dem gleichen Rechner laufen? Falls ja, ist es wahrscheinlicher dass das Problem an der Netzwerkkonfiguration liegt. Kannst Du Dich denn vom Raspi aus mit Telnet mit dem Server verbinden?
Majanao
User
Beiträge: 5
Registriert: Donnerstag 5. Januar 2017, 13:35

Bingo,
wenn ich Host und Client auf dem Pi laufen habe, funktioniert es. Jetzt ist die Frage wieso es über den Wlan-Router nicht klappen mag.
Hast du eine Idee?
Majanao
User
Beiträge: 5
Registriert: Donnerstag 5. Januar 2017, 13:35

Ok,
ich habe gerade nach deinem Tip noch etwas rumprobiert. Ich habe den Host nun auf den Pi gelegt und den Client auf meinen Rechner. Damit funktioniert es super.
Nur wieso läuft es nicht, wenn der Host auf dem PC läuft??

Vielen Dank für deine Hilfe!
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Majanao: Sternchenimporte sind schlecht. Wenn Du aus dem time-Modul nur sleep brauchst, dann importier das auch so »from time import sleep«. Nackte excepts (Zeile 44) solltest Du vermeiden. Das Fängt wirklich jeden Fehler, auch Programmierfehler (z.B. NameError) ab, und so wird es quasi unmöglich Fehlerquellen zu finden. Was für eine Exception möchtest Du denn an der Stelle verarbeiten? Bei einem Socket ohne »bind« braucht man SO_REUSEADDR nie (Zeile 55). Zeile 62/65: exit sollte nie außerhalb einer Hauptroutine aus aufgerufen werden, weil so wie jetzt »Client« nicht sinnvoll benutzt werden kann. Zeile 68: connect ist überflüssig, weil das schon in __init__ gemacht wird. Zeile 71ff: das was Du da mühsam selbst programmiert hast gibt es schon: socket.sendall.

Zum Problem: Du bindest den Server-Socket nur an den lokalen Host, d.h. Verbindungen von außerhalb werden geblockt. Das ist wahrscheinlich nicht, das was Du willst. Nimm als Host "0.0.0.0" um zu signalisieren, dass an jedem beliebige Gateway auf ankommende Verbindungen gewartet wird.
Majanao
User
Beiträge: 5
Registriert: Donnerstag 5. Januar 2017, 13:35

@Sirius3:
Vielen Dank für deine Anmerkungen. Du hattest Recht, da waren so einige Schnitzer im Code.

Die WLAN-Kommunikation funktionert jetzt, so lange der Host auf dem Pi läuft und der Client (PC) dem Host Daten (sendall) sendet. Jedoch muss für mein Projekt der Pi (Host) dem PC (Client) Daten schicken. Und genau das funktioniert nicht. Das Binden ist kein Problem, aber mein Skript hängt immer an client.recv(). Außerdem gibt es auf dem Host kein sendall.

Ist das vielleicht normal, dass der Host nicht zum Senden vieler Daten gedacht ist?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Majanao: Was heißt, hängt am recv? Warum gibt es auf dem Host kein sendall? Und falls es normal wäre, dass man nicht viele Daten senden kann, hätte das Netflix vielleicht schon gemerkt.

Mit anderen Worten: Du machst etwas falsch, um das aber herauszufinden brauchen wir Deinen Code.
Antworten