【问题标题】:Client disconnects when another client connects to the server当另一个客户端连接到服务器时客户端断开连接
【发布时间】:2020-07-21 00:02:54
【问题描述】:

我正在用 Python 编写一个加密的 R-P-S(石头、纸、剪刀)游戏,它的工作原理是这样的。服务器主导游戏,两个客户端只是将他们的选择发送到服务器。

首先,服务器在等待 2 名玩家加入,当 2 名玩家加入后,服务器开始游戏,让两个客户端选择一个选项。

我的问题是,当第一个客户端连接,然后另一个,第一个客户端自动断开连接。 所以,我不知道如何处理这两个客户端,让第一个客户端选择一个选项,然后让第二个选项选择。

*注意:我为两个客户端使用相同的客户端文件。

服务器:

import socket
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from time import sleep

def rules(first_choice, second_choice, mem1, mem2) -> str:
    if (first_choice == 'R' and second_choice == 'P' 
        or first_choice == 'P' and second_choice == 'S'
            or first_choice == 'S' and second_choice == 'R'):
                return f'Result: Player 2 Won\nPlayer 1 Choice - {first_choice}\nPlayer 2 Choice - {second_choice}'
    else:
        return f'Result: Player 1 Won!\nPlayer 1 Choice - {first_choice}\nPlayer 2 Choice - {second_choice}'

class Connect:
    def __init__(self):
        players = 0
        self.prikey = RSA.generate(1024)
        self.pubkey = self.prikey.publickey()
        self.token = PKCS1_OAEP.new(self.prikey)
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.bind(('0.0.0.0', 21523))
            sock.listen(2)
            print('Waiting for at least 2 players, please wait.')
            while True:
                self.conn, self.addr = sock.accept()
                players += 1
                if players == 1:
                    print(f'Player 1 is {self.addr}')
                    self.player1 = self.addr
                elif players == 2:
                    print(f'Player 2 is {self.addr}')
                    self.player2 = self.addr
                    self.connection()

    def connection(self) -> None:
        print('2 Players have joined, starting game in 5 seconds.\n')
        sleep(5)
        self.conn.send('Y'.encode())
        self.game_play()

    def game_play(self) -> None:
        self.conn.send(self.pubkey.exportKey())
        choice_1_cipher = self.conn.recv(1024)
        choice_1_plain = self.token.decrypt(choice_1_cipher)
        print('Got first choice, waiting for another choice..')
        choice_2_cipher = self.conn.recv(1024)
        choice_2_plain = self.token.decrypt(choice_2_cipher)
        print('Got second answer, calculating winner!')
        print(rules(choice_1_plain, choice_2_plain, self.player1, self.player2))

if __name__ == '__main__':
    Connect()

客户:

import socket
import random
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

class Client:
    def __init__(self):
        self.prikey = RSA.generate(2048)
        self.pubkey = self.prikey.publickey()
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect(('10.0.0.42', 21523))
        data = self.sock.recv(1024).decode()
        if data == 'Y':
            self.start_game()

    def start_game(self) -> None:
        print('\n [R]ock | [P]aper | [S]cissors - ')
        while True:
            my_choice = input().upper()
            if my_choice not in ['R', 'P', 'S']:
                print('Invalid Input, input must be one of those R\\P\\S')
            else:
                user_pubkey = RSA.importKey(self.sock.recv(2048))
                token = PKCS1_OAEP.new(user_pubkey)
                cipher_choice = token.encrypt(my_choice.encode())
                self.sock.send(cipher_choice)

if __name__ == '__main__':
    try:
        Client()
    except Exception as e:
        print(f'err: {e}')
    except KeyboardInterrupt:
        print('A player has pressed [Ctrl + C] to quit the game, game ended!')

【问题讨论】:

    标签: python sockets multiprocessing


    【解决方案1】:

    self.conn, self.addr = sock.accept() 中的self.conn 当 2 个客户端连接被覆盖并且 player1 的 self.conn 丢失时。 我想你应该将 self.conn 分配给self.player1_conn,然后返回到等待 2 玩家的 while 循环的开头。

    这实际上是您脚本中经常出现的问题,因为当您说 self.conn.send('Y'.encode()) self.conn 时仅指第二个玩家连接(我想这不是您打算做的)。

    您应该将player1_connplayer2_conn 中的conn 分开,然后您就可以选择向哪个玩家发送您需要的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      • 2016-07-06
      • 2010-11-01
      • 2018-12-14
      • 1970-01-01
      相关资源
      最近更新 更多