Hallo zusammen!
Ich bin sehr neu in Python und habe ein Problem bei folgendem Vorhaben:
Ich möchte einen Webserver laufen lassen (BaseHTTPServer) um damit eine Website zu hosten.
Parallel dazu soll ein TCP-Server laufen, welcher Verbindungsanfragen von einem Client erhält.
Sobald auf der Website ein Button getriggert wurde, möchte ich dem TCP-Client eine Nachricht senden.
Im Moment fange ich ich die Get-Requests des Webservers ab um die Parameter in der URL zu parsen, die mir der HTML-Button generiert (jeder Button
soll etwas anderes triggern). Dort ist es mir aber nicht möglich auf meinen TCP-Server zuzugreifen.
Ich verstehe noch nicht wirklich das Konzept mit den Handler-Klassen :K
Ich hoffe, dass war einigermaßen verständlich erklärt
LG,
Der Tele
TCP Request per Webserver triggern
Alles klar:
Ich habe versucht die Funktion in einer globalen Variable zu speichern um sie dann aufzurufen, aber das scheint auch nicht zu funktionieren.
LG,
Der Tele
Code: Alles auswählen
import cgi
import SocketServer
import threading
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
func_request = None
var_backendHandler = None
class BackendHandler(SocketServer.BaseRequestHandler):
def sendRequest(self, message):
self.request.sendall(message)
def handle(self):
print "New connection from {}".format(self.client_address[0])
while True:
d = self.request.recv(2000)
global func_request
func_request = self.sendRequest
global var_backendHandler
var_backendHandler = self
if not d:
break
print(d)
class ServerHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
if self.path.endswith(".html"):
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(f.read())
f.close()
return
if self.path.endswith(".html?btn_login=yes"):
func_request(var_backendHandler, "Function Call")
f = open(curdir + sep + "/index.html")
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(f.read())
f.close()
return
return
except IOError:
self.send_error(404, 'File not found: %s' % self.path)
def do_POST(self):
global rootnode
try:
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
if ctype == 'multipart/form-data':
query = cgi.parse_multipart(self.rfile, pdict)
self.send_response(301)
self.end_headers()
upfilecontent = query.get('upfile')
print("filecontent", upfilecontent[0])
self.wfile.write("<HTML>POST OK.<BR><BR>")
self.wfile.write(upfilecontent[0])
except:
pass
def main():
HOST, PORT = "localhost", 2310
try:
tcpServer = SocketServer.TCPServer((HOST, PORT), BackendHandler, bind_and_activate=False)
tcpServer.allow_reuse_address = True
webServer = HTTPServer(('', 80), ServerHandler)
threading.Thread(target=webServer.serve_forever).start()
tcpServer.server_bind()
tcpServer.server_activate()
tcpServer.serve_forever()
except KeyboardInterrupt:
print("Keyboard interrupt")
webServer.socket.close()
if __name__ == '__main__':
main()
LG,
Der Tele
@Tele: Warum kannst Du in einem Handler keine Anfrage an den TCP-Server schicken? Also was hält Dich technisch davon ab?
`BaseHTTPServer` würde ich übrigens höchstens zum Hosten von einer statischen Webseite verwenden. Falls da irgendwas dynamisches passieren soll würde ich eines der Mikrorahmenwerke, beispielsweise Bottle oder Flask, verwenden.
``global`` solltest Du ganz schnell vergessen.
Wenn der HTTP-Server auf das Socket-Server-Objekt zugreifen können soll dann muss man dem das übergeben, also einen eigenen, abgeleiteten Server schreiben. Der HTTP-Anfrage-Handler seinerseits kann auch auf seinen Server, und damit dann auch auf dessen Attribute zugreifen. Auf einen Socket-Server-Request von einem HTTP-Server-Request aus direkt zuzugreifen halte ich für unmöglich weil dazu parallel zum HTTP-Request ja ein Socket-Request existieren muss, und die müssen dann auch noch irgendwie zusammen gehören. Wie stellst Du das denn sicher?
Beschreib doch mal was Du *eigentlich* machen willst.
`BaseHTTPServer` würde ich übrigens höchstens zum Hosten von einer statischen Webseite verwenden. Falls da irgendwas dynamisches passieren soll würde ich eines der Mikrorahmenwerke, beispielsweise Bottle oder Flask, verwenden.
``global`` solltest Du ganz schnell vergessen.
Wenn der HTTP-Server auf das Socket-Server-Objekt zugreifen können soll dann muss man dem das übergeben, also einen eigenen, abgeleiteten Server schreiben. Der HTTP-Anfrage-Handler seinerseits kann auch auf seinen Server, und damit dann auch auf dessen Attribute zugreifen. Auf einen Socket-Server-Request von einem HTTP-Server-Request aus direkt zuzugreifen halte ich für unmöglich weil dazu parallel zum HTTP-Request ja ein Socket-Request existieren muss, und die müssen dann auch noch irgendwie zusammen gehören. Wie stellst Du das denn sicher?
Beschreib doch mal was Du *eigentlich* machen willst.
Oh das möchte ich gar nicht. Ich möchte von meinem WebserverHandler eine Methode des TCP-ServerHandler triggern (Wenn ich deine Frage richtig verstanden habe)BlackJack hat geschrieben:@Tele: Warum kannst Du in einem Handler keine Anfrage an den TCP-Server schicken? Also was hält Dich technisch davon ab?
Alles klarBlackJack hat geschrieben: `BaseHTTPServer` würde ich übrigens höchstens zum Hosten von einer statischen Webseite verwenden. Falls da irgendwas dynamisches passieren soll würde ich eines der Mikrorahmenwerke, beispielsweise Bottle oder Flask, verwenden.
``global`` solltest Du ganz schnell vergessen.
Folgendes:BlackJack hat geschrieben: Wenn der HTTP-Server auf das Socket-Server-Objekt zugreifen können soll dann muss man dem das übergeben, also einen eigenen, abgeleiteten Server schreiben. Der HTTP-Anfrage-Handler seinerseits kann auch auf seinen Server, und damit dann auch auf dessen Attribute zugreifen. Auf einen Socket-Server-Request von einem HTTP-Server-Request aus direkt zuzugreifen halte ich für unmöglich weil dazu parallel zum HTTP-Request ja ein Socket-Request existieren muss, und die müssen dann auch noch irgendwie zusammen gehören. Wie stellst Du das denn sicher?
Beschreib doch mal was Du *eigentlich* machen willst.
- Ich starte mein python Skript
- Client verbindet sich und wartet auf Antworten
- User geht auf die Website
- User klickt button
- Button triggert eine Nachricht per TCP-Server an den verbundenen Client
@Tele: Dann müsstest Du sowohl einen HTTP-Server als auch einen Socket-Server ableiten, den Socket-Server beim HTTP-Server bekannt machen, damit der dann eine Nachricht an den Socket-Server übergeben kann. Und der Socket-Handler müsste dann bei seinem Server auf so eine Nachricht warten. Eine `Queue.Queue` würde sich da anbieten, weil die schon von Haus aus threadsicher ist. Wobei ich wenn ich mir die `do_GET()`-Methode so anschaue wohl wirklich lieber Bottle oder etwas vergleichbares nehmen würde, statt von Hand auf diesem HTTP-Niveau zu arbeiten und URLs mit einfachen Zeichenkettenfunktionen zu untersuchen und das alles in einer Methode abzuhandeln.
Das nackte ``except:`` ohne eine konkrete Ausnahme in `do_POST()` ist nicht gut. Entweder behandelt man nur die Ausnahmen die man auch erwartet (also mindestens einen `NameError` bei dem Code), oder man protokolliert wenigstens was da so an Ausnahmen ausgelöst wurde. Sonst ist die Fehlersuche ein herumtapsen im dunkeln. An der Stelle sollte man das `logging`-Modul erwähnen. Das hat auch eine Funktion beziehungsweise `Logger` haben eine Methode um Ausnahmen zu protokollieren. Mit Traceback.
Das nackte ``except:`` ohne eine konkrete Ausnahme in `do_POST()` ist nicht gut. Entweder behandelt man nur die Ausnahmen die man auch erwartet (also mindestens einen `NameError` bei dem Code), oder man protokolliert wenigstens was da so an Ausnahmen ausgelöst wurde. Sonst ist die Fehlersuche ein herumtapsen im dunkeln. An der Stelle sollte man das `logging`-Modul erwähnen. Das hat auch eine Funktion beziehungsweise `Logger` haben eine Methode um Ausnahmen zu protokollieren. Mit Traceback.
Vielen Dank für die Hinweise, da werde ich mich drum kümmern.
Die Frage ist jetzt, wie ich in einer abgeleiteten Klasse von TCPServer einen Request an den Client schicke.
Bis jetzt handele ich die Requests ja in der BackendHandler-Klasse ab (sprich sendRequest(self, message))
Die Frage ist jetzt, wie ich in einer abgeleiteten Klasse von TCPServer einen Request an den Client schicke.
Bis jetzt handele ich die Requests ja in der BackendHandler-Klasse ab (sprich sendRequest(self, message))
Hallo nochmal!
Ich habe viel herumprobiert und bin auf web.py gestoßen und möchte es nun etwas "sauberer" per REST implementieren.
Leider scheitere ich diesmal an globalen Variablen. Ich möchte den REST-Server im Hintergrund laufen lassen.
Wenn eine neue Connection reinkommt, möchte ich diese in einem globalen socket-Objekt speichern um darauf eine Nachricht zu senden,
sollte ein REST Request reinkommen:
Leider bekomme ich immer ein print("Socket not initialized!") :K
Weiß jemand warum die globale Variable ihren Wert verliert/nicht zugewiesen wird?
LG,
Der Tele
Ich habe viel herumprobiert und bin auf web.py gestoßen und möchte es nun etwas "sauberer" per REST implementieren.
Leider scheitere ich diesmal an globalen Variablen. Ich möchte den REST-Server im Hintergrund laufen lassen.
Wenn eine neue Connection reinkommt, möchte ich diese in einem globalen socket-Objekt speichern um darauf eine Nachricht zu senden,
sollte ein REST Request reinkommen:
Code: Alles auswählen
import web
import SocketServer
import threading
# zu Testzwecken noch drin
class BackendHandler(SocketServer.BaseRequestHandler):
def handle(self):
print("New Connection: " + self.client_address[0])
while True:
data = self.request.recv(2000)
if not data:
break
self.data += data
print("Disconnected")
HOST, PORT = "localhost", 2310
server = SocketServer.TCPServer((HOST, PORT), BackendHandler, bind_and_activate=False)
sock = None
urls = (
'/', 'index',
'/start', 'start'
)
class index:
def GET(self):
return "Hello World!"
class start:
def GET(self):
global sock
print(sock)
if not sock:
print("Socket not initialized!")
return "Error - No connection!"
sock.send("start")
if __name__ == "__main__":
restServer = web.application(urls, globals())
threading.Thread(target=restServer.run).start()
server.allow_reuse_address = True
server.server_bind()
server.server_activate()
while True:
sock = server.get_request()[0]
print(sock)
msg = sock.recv(2000)
if not msg:
break
print(msg)
Weiß jemand warum die globale Variable ihren Wert verliert/nicht zugewiesen wird?
LG,
Der Tele