简体   繁体   中英

Twisted not sending data

server.py

from twisted.python import log
from twisted.internet import reactor,ssl, protocol
import config
import uuid
import json
import header

class cl:
    clients = list()
    source = None
    sourceID = None
    sent_header = list()
    id3_headers = {
        "pyc-title": "None",
        "pyc-length": "0",
    }

class RadioServer(protocol.Protocol):

    def connectionMade(self):
        if config.PyCasterMaxListeners != len(cl.clients):
            self.id = str(uuid.uuid4())
            self.peer = str(self.transport.getPeer())
            self.transport.write(header.header)
            cl.clients.append(self)
            print("Client-Connected-IP: "+self.peer)
            print("Client-Connected-ID: " + self.id)
        else:
            self.transport.abortConnection()

    def connectionLost(self, reason):
        if self.id == cl.sourceID:
            print("Source-Closed: "+ str(reason))
            cl.sourceID = None
            cl.source = None
        else:
            self.removeClient(self.id)
            print("Client-Closed-Reason: " + reason)
            print("Client-Closed-IP: " + self.peer)
            print("Client-Closed-ID: " + self.id)

    def dataReceived(self, data):
        dct = json.loads(data, encoding="utf8")
        if dct.has_key("PyCasterAuth"):
            if not cl.sourceID:
                auth = dct['PyCasterAuth']
                if auth == config.PyCasterAuth:
                    cl.source = self
                    cl.sourceID = self.id
                    self.transport.write("ok")
                    print("Source-Registered")
                    print("Source-ID: " + self.id)
                else:
                    cl.source.transport.write("denied")
                    print("Source-Login-Denied-IP: " + self.peer)
                    print("Source-Login-Denied-ID: " + self.id)
            else:
                print("Source-Exists-IP: " + self.peer)
                print("Source-Exists-ID: " + self.id)
                self.closeCl(self.id)
        elif dct.has_key("buffer"):
            buffer = dct['buffer']
            self.sendClients(buffer, bin=True)

        elif dct.has_key("info"):
            cl.id3_headers = dct['info']

    def removeClient(self, id):
        for client in cl.clients:
            if client.id == id:
                cl.clients.remove(cl)
                if client in cl.sent_header:
                    cl.sent_header.remove(client)

    def closeCl(self, id):
        for client in cl.clients:
            if client.id == id:
                self.removeClient(id)
                client.transport.abortConnection()
                print("Server-Closed-Client: (%s, %s)" % (id, client.peer))

    def sendClients(self, msg, bin=False):
        for client in cl.clients:
            if bin:
                if client not in cl.sent_header:
                    head = header.header
                    for k, v in iter(cl.id3_headers.items()):
                        head += k + ":" + v
                    client.transport.write("HTTP/1.1 200 OK\r\n")
                    client.transport.write(head)
            client.transport.write(msg)
            if config.PyCasterSendLogging:
                print("SENT %i bytes TO %s" % (len(msg), client.id))


if __name__=="__main__":
    import sys
    key = config.PyCasterSSLKey
    cert = config.PyCasterSSLCert
    factory = protocol.Factory()
    log.startLogging(sys.stdout)
    factory.protocol = RadioServer
    if config.PyCasterSSL:
        reactor.listenSSL(config.PyCasterPort, factory,  ssl.DefaultOpenSSLContextFactory(key, cert))
        reactor.run()
    else:
        reactor.listenTCP(config.PyCasterPort, factory)
        reactor.run()

config.py

PyCasterAuth = "123abc"
PyCasterPort = 4446
PyCasterSSL = False
PyCasterSSLKey = None
PyCasterSSLCert = None
PyCasterMaxListeners = 32
PyCasterSendLogging = True
PyCasterLogFile=open("pycaster.log", "w") #can be sys.stdout

header.py contains a variable of the header data to be sent

I provided the whole server so you can run and understand my issue. After the auth gets sent if its correct the server sends ok but the issue is self.transport.write("ok") doesn't get seen by the client. I've tried googling but I got no fixes.

So multiple issues with your approach. First of you all your inheriting the approach from an echo server and making your way out. And from the looks of it, it seems you need an HTTP Server. So look at below for example of request and response

http://twistedmatrix.com/documents/current/web/howto/web-in-60/dynamic-content.html

Also if you need to understand issues with your code. Then it is mainly your dataReceived.

def dataReceived(self, data):
    dct = json.loads(data, encoding="utf8")
    if dct.has_key("PyCasterAuth"):
        if not cl.sourceID:
            auth = dct['PyCasterAuth']
            if auth == config.PyCasterAuth:
                cl.source = self
                cl.sourceID = self.id
                self.transport.write("ok")
                print("Source-Registered")
                print("Source-ID: " + self.id)
            else:
                cl.source.transport.write("denied")
                print("Source-Login-Denied-IP: " + self.peer)
                print("Source-Login-Denied-ID: " + self.id)
        else:
            print("Source-Exists-IP: " + self.peer)
            print("Source-Exists-ID: " + self.id)
            self.closeCl(self.id)
    elif dct.has_key("buffer"):
        buffer = dct['buffer']
        self.sendClients(buffer, bin=True)

    elif dct.has_key("info"):
        cl.id3_headers = dct['info']

You are assuming data will have body. While that is not true, it will have the headers also. So your call will fail. A simple workaround you can add is below

    data_body = data.split(b"\r\n\r\n")[1]
    dct = json.loads(data_body, encoding="utf8")

Next key checking should be done like this

    if "PyCasterAuth" in dct:

as there is no method has_key . Also at the end of the dataReceived you want to close the request so it doesn't keep on waiting

self.transport.loseConnection()

So updated function is as below

def dataReceived(self, data):
    data_body = data.split(b"\r\n\r\n")[1]
    dct = json.loads(data_body, encoding="utf8")
    if "PyCasterAuth" in dct:
        if not cl.sourceID:
            auth = dct['PyCasterAuth']
            if auth == config.PyCasterAuth:
                cl.source = self
                cl.sourceID = self.id
                self.transport.write(b"ok")
                print("Source-Registered")
                print("Source-ID: " + self.id)
            else:
                cl.source.transport.write("denied")
                print("Source-Login-Denied-IP: " + self.peer)
                print("Source-Login-Denied-ID: " + self.id)
        else:
            print("Source-Exists-IP: " + self.peer)
            print("Source-Exists-ID: " + self.id)
            self.closeCl(self.id)
    elif dct.has_key("buffer"):
        buffer = dct['buffer']
        self.sendClients(buffer, bin=True)

    elif dct.has_key("info"):
        cl.id3_headers = dct['info']

    self.transport.loseConnection()

But as I mentioned you should not be using this approach rather one from the link I added.

Below is a simple test

 curl -v -H "Content-Type: application/json" -X POST -d '{"PyCasterAuth":"123abc"}' localhost:4446
Note: Unnecessary use of -X or --request, POST is already inferred.
* Rebuilt URL to: localhost:4446/
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 4446 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4446 (#0)
> POST / HTTP/1.1
> Host: localhost:4446
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 25
>
* upload completely sent off: 25 out of 25 bytes
Name: Tarun
* Connection #0 to host localhost left intact
ok%

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM