关于python:将控制权返回给传输

return control to the transport

我试图模拟一种情况,即服务器定期接收数据。在我的设置中,我运行一个设置服务器的进程和另一个设置大量客户机的进程(足以考虑单个客户机)。我已经设置了一些代码,主要是从这里把零碎的东西放在一起。服务器/客户端通过使用transport.write发送消息进行通信。首先,服务器告诉客户机启动(这对Afaik很好)。客户机在取得进展时向服务器报告。令我困惑的是,当客户机完成时,我只会在最后得到这些间歇的消息。这可能是缓冲区刷新的问题,我尝试过(没有成功)类似的操作。另外,每个消息都非常大,我多次尝试发送相同的消息,以便清除缓冲区。

我怀疑我看到的是把控制权交还给运输部门的问题,但我不知道该如何处理。

任何帮助这或任何其他问题跳到你是非常感谢。

服务器:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from twisted.internet import reactor, protocol

import time
import serverSideAnalysis
import pdb
#import bson, json, msgpack
import _pickle as pickle  # I expect the users to authenticate and not
                          # do anything malicious.


PORT = 9000
NUM = 1
local_scratch="/local/scratch"


class Hub(protocol.Protocol):
  def __init__(self,factory, clients, nclients):
    self.clients = clients
    self.nclients = nclients
    self.factory = factory
    self.dispatcher = serverSideAnalysis.ServerTalker(NUM, self,
          local_scratch)

  def connectionMade(self):
    print("connected to user" , (self))
    if len(self.clients) < self.nclients:
      self.factory.clients.append(self)
    else:
      self.factory.clients[self.nclients] = self
    if len(self.clients) == NUM:
      val = input("Looks like everyone is here, shall we start? (Y/N)")
      while (val.upper() !="Y"):
        time.sleep(20)
        val = input("Looks like everyone is here, shall we start??? (Y/N)")
      message = pickle.dumps({"TASK":"INIT","SUBTASK":"STORE"})
      self.message(message) # This reaches the client as I had expected

  def message(self, command):
    for c in self.factory.clients:
      c.transport.write(command)

  def connectionLost(self, reason):
    self.factory.clients.remove(self)
    self.nclients -= 1

  def dataReceived(self, data):
    if len(self.clients) == NUM:
      self.dispatcher.dispatch(data)

class PauseTransport(protocol.Protocol):
  def makeConnection(self, transport):
    transport.pauseProducing()

class HubFactory(protocol.Factory):
  def __init__(self, num):
    self.clients = set([])
    self.nclients = 0
    self.totConnections = num

  def buildProtocol(self, addr):
    print(self.nclients)
    if self.nclients < self.totConnections:
      self.nclients += 1
      return Hub(self, self.clients, self.nclients)
    protocol = PauseTransport()
    protocol.factory = self
    return protocol

factory = HubFactory(NUM)
reactor.listenTCP(PORT, factory)
factory.clients = []
reactor.run()

客户:

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
40
41
42
43
44
45
46
47
from twisted.internet import reactor, protocol
import time
import clientSideAnalysis
import sys


HOST = 'localhost'
PORT = 9000
local_scratch="/local/scratch"

class MyClient(protocol.Protocol):

  def connectionMade(self):
    print("connected!")
    self.factory.clients.append(self)
    print ("clients are", self.factory.clients)

    self.cdispatcher = clientSideAnalysis.ServerTalker(analysis_file_name, local_scratch, self)

  def clientConnectionLost(self, reason):
    #TODO send warning
    self.factory.clients.remove(self)

  def dataReceived(self, data): #This is the problematic part I think
    self.cdispatcher.dispatch(data)
    print("1 sent")
    time.sleep(10)
    self.cdispatcher.dispatch(data)
    print("2 sent")
    time.sleep(10)
    self.cdispatcher.dispatch(data)
    time.sleep(10)


  def message(self, data):
    self.transport.write(data)

class MyClientFactory(protocol.ClientFactory):
  protocol = MyClient

if __name__=="__main__":
  analysis_file_name = sys.argv[1]

  factory = MyClientFactory()
  reactor.connectTCP(HOST, PORT, factory)
  factory.clients = []
  reactor.run()

关于调度员所做工作的最后一点相关信息。

在这两种情况下,它们都会加载已到达的消息(字典),并根据内容进行一些计算。每隔一段时间,他们就会使用message方法与更大的电流值进行通信。

最后,我使用的是Python3.6。扭曲18.9.0


从protocol.dataReceived方法将控制权返回到reactor的方法是从该方法返回。例如:

1
2
3
def dataReceived(self, data):
    self.cdispatcher.dispatch(data)
    print("1 sent")

如果你想在这之后做更多的工作,你有一些选择。如果您希望在经过一段时间后完成工作,请使用reactor.callLater。如果您希望工作在发送到另一个线程之后发生,请使用twisted.internet.threads.deferToThread。如果您希望在响应其他事件(例如,正在接收的数据)时执行工作,请将其放入处理该事件的回调(例如,dataReceived)。