ich kämpf grade mit Sockets und stecke dabei ein wenig fest. Ich habe über 2 Stunden ein Fehler gesucht und nicht gefunden. Beim zusammenkürzen des Codes ist es mir aber grade bewusst gewurden. Ich fang erstmal von vorne an. Ich will mehrer Clients fernsteuern. Dazu habe ich einen Server (der grade das Problem ist) auf den sich die Clients verbinden, auf Befehle warten und ggf. eine Antwort zurück schicken. Meine Hoffnung war das es dafür schon sinnvolle Bibliotheken gibt... naja. Dass was ich gefunden habe, brachte Abhängigkeiten mit die ich nicht erfüllen will/kann, oder der Code sah schon müllig aus. Deswegen habe ich mich entscheiden das mit Socktes zusammen zu bauen/frickeln. Jetzt habe ich mit meiner Lösung ein Problem. Schicke ich ein Befehl an den Client und hole die Antwort direkt ab, fehlen von der Antwort die ersten acht Byte (proxy_server.test() / auskommentierte Zeilen) und es gibt ein Fehler weil die Sturktur der Nachricht fehlerhaft ist. Hole ich mir nicht direkt die Antwort, bekommen ich sie automatisch und vollständig von proxy_node.handle() ausgegeben. Ich habe 2 Stunden nicht verstanden warum. Erst beim zusammenkürzen des Codes ist mir klar gewurden. Das ist ein Threading Problem. proxy_node.handle() und proxy_server.test() laufen in unterschiedlichen Threads. Der eine Thread wartet immer auf neuen Nachrichten des Sockets, wenn noch ein zweiter Thread das selbe macht zerhackt es die Nachrichten und es knallt.
Wie umgehen ich das Problem am sinnvollsten? Ich hab leider mit Threading sogut wie keine Erfahrung, was übringens auch für Python gilt. Ich hab zwei Ideen und die sind unbrauchbar. Einmal die proxy_node.handle() Funktion nicht mehr auf den Socket lesen zu lassen, sondern nur noch gezielt den socket auslesen. Das funktioniert aber nicht, weil auch der Client die Komunikation initiallisieren muss. Die andere Idee war die letzte Nachricht über proxy_node.handle() in proxy_node zu speichern und dort raus die Nachrichten zu holen. Das ist aber völliger Humbug, weil ich auf gut Glück warten müsste um eine Nachricht auszulesen. Ich bin eigentlich offen für alles. Von komplett anders, bis "ist zwar Pfusch, aber so und so könnte das gehen". Das ist nur ein "Spassprojekt".
Code aufs wesentliche gekürzt:
Code: Alles auswählen
import socketserver
import threading
import time
import random
import builtins
import netcore
class proxy_node(socketserver.BaseRequestHandler):
def handle(self):
while True:
try:
data = netcore.reciveJson(self.request)
if data == False:
return False
except ConnectionResetError:
return False
print(data['cmd'])
print(data)
class proxy_server(socketserver.ThreadingMixIn, socketserver.TCPServer):
proxy_nodes = []
def test(self):
proxy_node = self.getAvailableProxyNode()
netcore.sendJson(proxy_node.request, {'cmd': 'test'})
#response = netcore.reciveJson(proxy_node.request)
#print(response)
if __name__ == "__main__":
HOST, PORT = "", 9999
server = proxy_server((HOST, PORT), proxy_node)
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
while 1:
command = input('CMD > ')
if command == 't':
server.test()
Netzwerkcode um aus dem Stream Nachrichten zu machen:
Code: Alles auswählen
import json
import struct
def reciveMessage(socket):
data = socket.recv(8)
message = b''
if not data:
return False
if data[0:2] != b'LE' and data[6:8] != b'LE':
print('unkown format')
print(data)
return False
len = struct.unpack('>I', data[2:6])[0]
while True:
data = socket.recv(len)
if not data:
return False
message += data
if message.__len__() >= len:
break;
return message
def sendMessage(socket, message):
pack1 = struct.pack('>I', len(message))
message = b'LE'+pack1+b'LE'+message
socket.sendall(message)
def reciveJson(socket):
message = reciveMessage(socket)
if message == False:
return False
message = message.decode('utf8')
return json.loads(message)
def sendJson(socket, obj):
message = json.dumps(obj)
sendMessage(socket, bytes(message, 'utf8'))