0

Twisted ソケットとやり取りしてオンライン ゲームプレイを可能にする Blackjack iPhone アプリを開発中です。現時点での私の問題は、適切なポートを見つけることです。説明させてください。

「テーブル」というクラスを作成しました。ポジション、プレイヤー、カード デッキなど、ブラックジャック テーブルのような情報を保持します。1 つの Twisted ソケットに 1 つのテーブルが割り当てられ、1 つのポートに 1 つのソケットが割り当てられます。現在、ポート 1025 ~ 1034 のみをテストしています。

私が実現したいのは、ポートの昇順で各テーブルのプレイヤー数を取得するアプリ リクエストです。テストのために、テーブルに 1 人のユーザーのみを許可します。1 人のユーザーがテーブルにいる場合、ソケットが 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()
4

1 に答える 1

2

あなたが抱えている主な問題はtable = Table()、ソケットクラスにあります。これは、これまでのすべてのSocketインスタンスで、 が 1 つしかないことを意味しますTable

簡単な解決策は、それぞれを に保存Tableして、そのポート (つまり、リッスンしている TCP ポート)Factoryへのすべての接続が単一のインスタンスを共有するようにすることです。FactoryTable

これは、行を削除してから、次のようにループ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ますTable

ただし、このコードには他にも多くの重大な問題があります。

  • このプロトコルに複数のポートを使用する必要はなく、使用するべきではありません。それぞれの新しい接続が表示され、プロトコル自体を介したメッセージでプレイしたいブラックジャック ゲームを特定する必要があります。複数のポートで作業すると、人々がファイアウォールを通過してゲームをプレイするのが難しくなります。適切なインスタンスtableに属性を設定するだけで、同じ戦略を使用できます。Socket

  • dataReceivedメッセージ全体で呼び出される ことを期待しています。これは Twisted のドキュメントで読むべき FAQ です。 というか、実際のインターネットに展開するときではなく、テストしているときになります。iPhone の開発を行っている場合は、Network Link Conditioner を使用して実際のインターネット接続をシミュレートする必要があります。

  • あなたはネットワーク プロトコルの解析がどのように機能するかを理解していないようなので、プロトコル構築キットなどAMPを使用してワイヤ プロトコルを構築する必要があります。 API ドキュメントには、簡単なチュートリアルが含まれています。

  • を呼び出していますtime.sleep。それはサーバー全体をブロックします。これは、時間に敏感な Twisted サービスを構築するための間違った方法です。さらに重要なことに、Twisted はブロックされている間は入力を処理しませんtime.sleep。そのため、すべてのプレイヤーはカードをプレイするのではなく、常に即座に降伏します。callLater代わりに、ゲームの状態を変更する時限呼び出しをスケジュールするために使用する必要があります。

あなたが抱えている問題のほとんどはオブジェクト構成の問題であり、Twisted や Python に固有のものではありません。どのインスタンスが他の何を指しているべきかを示すマップを自分で作成する必要があります。理解しておくべき重要なことは、listenTCPやのようにリアクターを呼び出すcallLater場合、設定しているのはリアクターからオブジェクトへの参照であることです。それについて魔法は何もありません。「後で、このオブジェクトで、この状況下でこのメソッドを呼び出す」と言っているだけです。そこからすべてが流れ出します。テーブルへの参照を持つソケット、プレーヤーへの参照を持つテーブルなど。

于 2012-06-03T20:58:13.037 に答える