Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

1

06.08.2016, 23:07

[Python] String via TCP-Socket senden

Hallo,
ich habe das Problem, dass ich in einer Methode keine Strings (die vorher deklariert und definiert wurden) zu senden. Der Code ist folgender:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Server:
    def __init__(self):
        self.HOST = '192.168.178.55'
        self.PORT = 6666
        self.server_address = (self.HOST, self.PORT)
        self.connected = False
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        print ('starting up on %s port %s' % self.server_address, file=sys.stderr)
        self.sock.bind(self.server_address) 
        self.sock.listen(10)
        
        threading.Thread.__init__(self)
        self.t1 = threading.Thread(target=self.run)
        self.t1.daemon = True
        self.t1.start()

    def run(self):
        while True:
            if self.connected == False:
                # Wait for a connection
                global connected, client, client_address

                connected = True
                print ('waiting for a connection', file=sys.stderr)
                client, client_address  = self.sock.accept()
                print ('connection from', client_address, file=sys.stderr)
                #print (connected, file=sys.stderr)

    def send_to_client(self, string):
        global client, connected 
        if connected == True:
            print (string, file=sys.stderr)
            client.send(string.encode())


Fehlerausgabe:
Traceback (most recent call last):
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\app.py", line 1643, in full_dispatch_request
response = self.process_response(response)
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\app.py", line 1864, in process_response
self.save_session(ctx.session, response)
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\app.py", line 926, in save_session
return self.session_interface.save_session(self, session, response)
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\sessions.py", line 359, in save_session
val = self.get_signing_serializer(app).dumps(dict(session))
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\itsdangerous.py", line 565, in dumps
payload = want_bytes(self.dump_payload(obj))
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\itsdangerous.py", line 847, in dump_payload
json = super(URLSafeSerializerMixin, self).dump_payload(obj)
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\itsdangerous.py", line 550, in dump_payload
return want_bytes(self.serializer.dumps(obj))
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\sessions.py", line 85, in dumps
return json.dumps(_tag(value), separators=(',', ':'))
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\json.py", line 126, in dumps
rv = _json.dumps(obj, **kwargs)
File "C:\Python34\lib\json\__init__.py", line 237, in dumps
**kw).encode(obj)
File "C:\Python34\lib\json\encoder.py", line 192, in encode
chunks = self.iterencode(o, _one_shot=True)
File "C:\Python34\lib\json\encoder.py", line 250, in iterencode
return _iterencode(o, 0)
File "E:\Programmieren\Projekte\Phython\Flask\FlaskWebProject1\FlaskWebProject1\env\lib\site-packages\flask\json.py", line 83, in default
return _json.JSONEncoder.default(self, o)
File "C:\Python34\lib\json\encoder.py", line 173, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: OSError(10057, 'Eine Anforderung zum Senden oder Empfangen von Daten wurde verhindert, da der Socket nicht verbunden ist und (beim Senden über einen Datagrammsocket mit einem sendto-Aufruf) keine Adresse angegeben wurde', None, 10057, None) is not JSON serializable

Kann jemand helfen?
Danke im Voraus :D

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

2

07.08.2016, 00:31

Dumme Vermutung: in Zeile 25 wird die globale Variable connected auf True gesetzt, unabhängig davon, ob sich ein Client verbindet. Da keine Verbindung besteht, kann nichts gesendet werden.
Insgesamt sollte das aber so ein Problem sein, wo ein Debugger hilfreich sein dürfte.

Mein Vorschlag: verwende kein global.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

3

07.08.2016, 00:46

Das Problem besteht darin dass man mit Thread einen "locale storage" setzt. Das heißt alle Variablen die man da definiert sind nur lokal verfügbar. Und Du hast natürlich Recht, dass die Variable "connected" nicht wieder zurückgesetzt wird. Dass liegt aber daran, dass ich noch keine Ahnung habe wie ich prüfe, ob die Verbindung mit dem Client abgebrochen wurde.

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

4

07.08.2016, 10:18

Das heißt alle Variablen die man da definiert [...]
Wo? Variablen innerhalb von Fuktionen sind lokale Variablen und somit immer lokal. Wenn du diese an mehreren Stellen verwenden willst, dann musst du sie an anderer Stelle anlegen. Ich hatte in Python bereits mit Threading gearbeitet und hatte bisher keine Probleme, einfach die gleichen Variablen (also Member des Objekts, welches die vom Thread ausgeführte Methode beinhaltet) zuzugreifen.
Wie geschrieben: baue dein Zeug erstmal so um, dass kein global mehr notwendig ist. Wenn du nicht anhand des Client-Sockets ablesen kannst, ob die Verbindung bereits aufgebaut wurde, solltest du diese mit einer Klasse wrappen und zusätzlich Informationen (wie "ist verbunden") dazu packen. Allerdings sollte der Code ohnehin keinen Zugriff auf einen invaliden Client erhalten, entsprechend musst du auch an anderer Stelle noch schauen, dass nur dann ein Socket vorhanden ist, wenn darauf zugegriffen werden kann (-> kein global).
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

5

07.08.2016, 12:21

Zuerst haben ich das ganze ohne global gemacht. Das Problem war nur, dass die gleiche Variable (in einer Memberfunktion) einen anderen Wert hatte, als zuvor gesetzt wurde. Und im Internet haben alle zu global geraten, obwohl das ein schlechter Codestil ist.

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

6

07.08.2016, 19:02

Und wie wäre es mit Membervariablen?
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

7

07.08.2016, 21:15

Membervariablen haben wir verendet. Wir haben es mit "self." implementiert ^^

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

8

07.08.2016, 22:05

... und? Ich würde dir noch immer von globalen Variablen abraten. Wenn es ohne nicht funktioniert hat, kann es sein, dass es vorher einfach falsch implementiert wurde und deswegen fehlerhaft war.

Bedenke, dass "connected" keine Eigenschaft des Servers ist.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

9

07.08.2016, 22:40

Ich wuerde ebenfalls ganz stark von globals abraten, vor allem wenn du mit mehreren Threads umgehst.

Ein weiterer Fehler ist, dass du connected = True setzt bevor du eine Verbindung auf dem socket bekommen hast.

Das mit dem local storage ist quatsch. Es gibt einen thread local storage ueber threading.local(), aber es wird nicht automatisch alles was du in einem thread setzts auch darin gespeichert. Du kannst connected/client also durchaus als membervariable speichern.

PS: Ich habe das Gefuehl, dass bei dem ganzen Konzept was du da machst etwas im argen ist. Du startest einen extra Server Thread auf einem Flask web server, der auf eine Verbindung wartet und dann der Verbindung etwas schickt? Alles in einem GET request? Das klingt alles sehr merkwuerdig.

10

08.08.2016, 23:44

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import socket
import sys
import threading
            
##############################################################################

class Server:
    def __init__(self):
        self.server_address = ('192.168.178.43', 6666)
        self.connected = False
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        print ('starting up on %s port %s' % self.server_address, file=sys.stderr)
        self.sock.bind(self.server_address) 
        self.sock.listen(10)

        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client_address = ''
        self.connected = False
        
        threading.Thread.__init__(self)
        self.t1 = threading.Thread(target=self.run)
        self.t1.daemon = True
        self.t1.start()

    def run(self):
        # Wait for a connection          
        print ('waiting for a connection', file=sys.stderr)
        self.client, self.client_address = self.sock.accept()
        print ('connection from', self.client_address, file=sys.stderr)       
        self.connected = True
        print (self.connected, file=sys.stderr) #Hier wird zur Laufzeit True ausgegeben.

    def send_to_client(self, data):
        print (self.connected, file=sys.stderr) #Und hier dann False. Wieso ???
        if self.connected == True:
            print (data, file=sys.stderr)
            self.client.send(data)


So sieht es aus wenn wir dass mit normalen Membervariablen machen. In der Funktion "run" wird die Membervariable "connected" auf True gesetzt, und bewusst erstmal nicht wieder auf False gesetzt. Wenn man jetzt die Funktion "send_to_client()" aufruft, dann wird für die Variable "connected" False ausgegeben.

MfG

Werbeanzeige