我正在开发一款与Twisted套接字交互的Blackjack iPhone应用程序,以允许在线游戏。我现在的问题是找到合适的端口。让我解释一下。
我创建了一个名为“Table”的类。它拥有像二十一点牌这样的信息,比如位置,玩家和牌组。一个表分配给一个Twisted套接字,一个套接字分配给一个端口。现在,我只测试端口1025-1034。
我想要发生的是应用程序请求通过按端口升序顺序获取每个表的玩家数量。为了测试,我只允许一个用户在一张桌子上。如果一个用户在一个表,我希望套接字返回Table_Not_Found,但是,即使用户在一个表,套接字也会返回一个人所在的端口,而不是下一个没有人的端口。
我认为我没有正确使用Table类并搜索打开的表。我怎样才能找到合适的端口?应用程序连接到端口,如果端口被占用,则返回Table_Not_Found,然后应用程序请求下一个端口可用。但在我的情况下,套接字总是返回所采用的端口。我只能用我的iMac和MacBook进行测试,因为他们是客户。
底线,如何在端口上搜索可用的表?
谢谢!
class Table:
def __init__(self):
self.players = []
self.positions = []
self.id = 0
self.numberOfPlayers = 0
def setID(self, _id):
self.id = _id
def setActivePlayer(self, player):
player.countdown = 20
while player.count > 0:
print player.countdown
time.sleep(1)
player.countdown -= 1
if player.countdown == 0:
print "Out of time"
moves.surrender(player)
class Socket(Protocol):
table = Table()
def connectionMade(self):
#self.transport.write("""connected""")
self.factory.clients.append(self)
print "Clients are ", self.factory.clients
def connectionLost(self, reason):
self.factory.clients.remove(self)
def dataReceived(self, data):
#print "data is ", data
a = data.split(':')
if len(a) > 1:
command = a[0]
content = a[1]
b = content.split(';')
_UDID = b[0].replace('\n', '')
if command == "Number_of_Players":
if Socket.table.numberOfPlayers == 0:
msg = "%s:TableFound" % _UDID
elif Socket.table.numberOfPlayers == 1:
msg = "%s:Table_Not_Found" % _UDID
print msg
for c in self.factory.clients:
c.message(msg)
def message(self, message):
self.transport.write(message)
NUM_TABLES = 10
factories = [ ]
for i in range(0, NUM_TABLES):
print i
factory = Factory()
factory.protocol = Socket
factory.clients = []
factories.append(factory)
reactor.listenTCP(1025+i, factory)
#print "Blackjack server started"
reactor.run()
答案 0 :(得分:2)
您遇到的主要问题是套接字类中的table = Table()
。这意味着,对于所有Socket
个实例,只有一个Table
。
快速解决方法是将每个Table
存储在Factory
上,以便与Factory
的所有连接(即侦听TCP端口)将共享一个Table
实例
这可以通过删除table = Table()
行,然后像这样修改for
循环来实现:
for i in range(0, NUM_TABLES):
print i
factory = Factory()
factory.table = Table() # <-- add this line
factory.protocol = Socket
factory.clients = []
factories.append(factory)
reactor.listenTCP(1025+i, factory)
然后将connectionMade
调整为以这样的方式开始:
def connectionMade(self):
self.table = self.factory.table
现在每个Socket
都指向Factory
的{{1}}。
但是,此代码存在许多其他严重问题:
您不需要也不应该使用此协议的多个端口。每个新连接都应该显示并通过协议本身识别它想要播放的二十一点游戏。在多个端口上工作只会让人们更难通过防火墙来玩游戏。您可以使用相同的策略,只需在相应的Table
实例上设置table
属性。
您希望使用完整邮件调用Socket
。 It won't be, and this is a FAQ that you should read in the Twisted docs.或者更确切地说,它将在您进行测试时,但在部署到真正的互联网时则不会。如果您正在进行iPhone开发,则应使用网络链接调节器来模拟真实的互联网连接。
由于您似乎不知道网络协议解析的工作原理,因此您应该使用a protocol construction kit like AMP
来构建有线协议。 The API documentation includes a brief tutorial.
您正在呼叫dataReceived
。这将阻止整个服务器。这是构建时间敏感的Twisted服务的错误方法。更重要的是,Twisted不会在等待time.sleep
完成时阻止输入,因此每个玩家都会立即投降,而不是能够玩任何牌。您应该使用callLater
来安排改变游戏状态的定时通话。
你遇到的大多数问题都是对象组合问题,而不是Twisted或Python特有的问题。您需要为自己绘制一个地图,指出哪些实例应指向其他内容。需要了解的重要一点是,当您调用反应堆(如time.sleep
或listenTCP
)时,您所设置的是从反应堆到您的物体的参考。这没有什么神奇之处;你只是说“以后,在这种情况下,在这个对象上调用这种方法”。一切都从那里流出来;你的套接字引用了你的表,你的表引用了它们的玩家,等等。