扭曲的套接字端口和类

时间:2012-06-03 04:30:29

标签: python ios sockets twisted

我正在开发一款与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()

1 个答案:

答案 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属性。

  • 您希望使用完整邮件调用SocketIt 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.sleeplistenTCP)时,您所设置的是从反应堆到您的物体的参考。这没有什么神奇之处;你只是说“以后,在这种情况下,在这个对象上调用这种方法”。一切都从那里流出来;你的套接字引用了你的表,你的表引用了它们的玩家,等等。