2017-01-22 1 views
0

Mon serveur est configuré pour cocher et mettre à jour tous les clients toutes les 100ms - voir self.TICKS_PER_SECOND = 10, 1000/10 = 100ms. Cependant, l '"horloge" dans le code HTML n'est mise à jour que toutes les secondes. Pourquoi?Pourquoi le serveur met à jour les clients toutes les secondes au lieu de 100 ms - code source complet disponible

Si je continue à cliquer sur le bouton Envoyer, l'horloge sera mise à jour plus rapidement. Pourquoi?

app.py

import logging 
import sys 
from datetime import datetime 
import time 
current_milli_time = lambda: int(round(time.time() * 1000)) 

import json 
import threading 

from twisted.web.static import File 
from twisted.python import log 
from twisted.web.server import Site 
from twisted.web.resource import Resource 

from twisted.internet import pollreactor 
pollreactor.install() 

from twisted.internet import reactor 

from autobahn.twisted.websocket import WebSocketServerFactory, \ 
    WebSocketServerProtocol 

from autobahn.twisted.resource import WebSocketResource 


class AppGameServerProtocol(WebSocketServerProtocol): 

    def onOpen(self): 
     """ 
     """ 
     self.factory.register(self) 
     self.factory.onConnected(self) 

    def onConnect(self, request): 
     print("Client connecting: {}".format(request.peer)) 

    def connectionLost(self, reason): 
     self.factory.unregister(self) 

    def onMessage(self, payload, isBinary): 
     self.factory.communicate(self, payload, isBinary) 


class AppGameFactory(WebSocketServerFactory): 

    def __init__(self, *args, **kwargs): 
     super(AppGameFactory, self).__init__(*args, **kwargs) 
     self.clients = {} 

    def register(self, client): 
     self.clients[client.peer] = {"object": client, "partner": None} 

    def unregister(self, client): 
     self.clients.pop(client.peer) 


    def onConnected(self,client): 
     client.sendMessage(json.dumps({"type": "connect"})) 

    def communicate(self, client, payload, isBinary): 
     print "msg received", payload 

    def sendMessageAll(self, message): 
     for i in self.clients: 
      c = self.clients[i] 
      c["object"].sendMessage(message) 

class SummingThread(threading.Thread): 
    def __init__(self, fac): 
     super(SummingThread, self).__init__() 
     self.fac = fac 

     self.TICKS_PER_SECOND = 10 
     self.SKIP_TICKS = 1000/self.TICKS_PER_SECOND 
     self.MAX_FRAMESKIP = 5 
     self.loops = 0 
     self.next_game_tick = current_milli_time() 

    def run(self): 
     while True: 
      self.loops = 0 
      while current_milli_time() > self.next_game_tick and self.loops < self.MAX_FRAMESKIP: 

       self.fac.sendMessageAll("clock: " + datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]) 
       self.next_game_tick += self.SKIP_TICKS 
       self.loops += 1 



if __name__ == "__main__": 
    log.startLogging(sys.stdout) 

    factory = AppGameFactory(u"ws://127.0.0.1:8080") 
    factory.protocol = AppGameServerProtocol 
    resource = WebSocketResource(factory) 

    root = Resource() 
    root.putChild('', File('index.html')) 

    root.putChild(u"ws", resource) 

    thread1 = SummingThread(factory) 
    thread1.start() 

    try: 
     site = Site(root) 
     reactor.listenTCP(8080, site) 
     reactor.run() 
    except Exception as e: 
     logging.exception("message") 

index.html

<!DOCTYPE html> 
<html> 
<head> 
    <script type="text/javascript"> 
     window.addEventListener("load", function() { 

      var msgReceived = 0 

      // create websocket instance 
      var mySocket = new WebSocket("ws://localhost:8080/ws"); 

      // add event listener reacting when message is received 
      mySocket.onmessage = function (event) { 
       var output = document.getElementById("output"); 
       // put text into our output div 
       msgReceived++; 
       output.textContent = event.data + " msgReceived: " + msgReceived; 
       //console.log(event.data); 
      }; 

      var form = document.getElementsByClassName("foo"); 
      var input = document.getElementById("input"); 

      form[0].addEventListener("submit", function (e) { 
       // on forms submission send input to our server 
       input_text = input.value; 
       mySocket.send(input_text); 
       e.preventDefault() 
      }) 
     }); 

    </script> 
<style> 
    /* just some super ugly css to make things bit more readable*/ 
    div { 
     margin: 2em; 
    } 
    form { 
     margin: 2em; 
    } 
</style> 
</head> 
<body> 
    <form class="foo"> 
     <input id="input"></input> 
     <input type="submit"></input> 
    </form> 
    <div id="output"></div> 
</body> 
</html> 

Répondre

0

Vous appelez API Twisted de plusieurs threads. Ceci n'est pas autorisé. Vous ne pouvez appeler des API Twisted qu'à partir du thread du réacteur, à l'exception de quelques API spécifiques aux threads. Principalement reactor.callFromThread qui planifie une fonction à exécuter dans le fil du réacteur. Envisager de remplacer SummingThread par une construction basée sur twisted.internet.task.LoopingCall.

Par exemple:

from twisted.internet.task import LoopingCall 

def game_tick(factory, skip_count): 
    now = datetime.utcnow() 
    factory.sendMessageAll(
     "clock: " + now.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] 
    ) 


factory = # ... 
task = LoopingCall.withCount(partial(game_tick, factory)) 
task.start(0.1) 
# ... 
reactor.run() 

game_tick sera appelé dix fois par seconde (ou, si moins souvent parce que la charge est trop élevée ou un autre problème, skip_count sera mis plus d'un pour indiquer combien de tiques ont été manqués).