简体   繁体   English

当另一个客户端连接到服务器时客户端断开连接

[英]Client disconnects when another client connects to the server

I'm writing an Encrypted RPS (Rock, Paper, Scissors) Game with Python, and it works like this.我正在用 Python 编写一个加密的 RPS(石头、纸、剪刀)游戏,它的工作原理是这样的。 The server is leading the game, and the two clients is just sending their choice to the server.服务器主导游戏,两个客户端只是将他们的选择发送到服务器。

First, the server is waiting for 2 players to join, when 2 players have joined, he is starting the game and letting both of the clients to choice an option.首先,服务器正在等待 2 名玩家加入,当 2 名玩家加入时,他正在开始游戏并让两个客户端选择一个选项。

My problem is that when the first client connects, and then the another, the first client automatically disconnects.我的问题是,当第一个客户端连接时,然后另一个客户端会自动断开连接。 So, I don't know how to handle both of the clients, and let the first client choose an option and then let the second choose option.所以,我不知道如何处理两个客户,让第一个客户选择一个选项,然后让第二个客户选择一个选项。

*Note: I'm using the same client file for both of the clients. *注意:我为两个客户端使用相同的客户端文件。

Server:服务器:

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()

Client:客户:

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!')

self.conn in self.conn, self.addr = sock.accept() when the 2 client connects gets overwritten and the self.conn of the player1 is lost. self.conn中的self.conn, self.addr = sock.accept()当 2 个客户端连接时被覆盖,并且 player1 的 self.conn 丢失。 I guess you should assign the self.conn to self.player1_conn before returning to the beginning of the while loop waiting for the 2 player.我想您应该将 self.conn 分配给self.player1_conn ,然后返回到等待 2 玩家的 while 循环的开头。

This is actually a recurrent problem in your script because when you say self.conn.send('Y'.encode()) self.conn is referring only to the second player connection (which i guess it's not what you intend to do).这实际上是您的脚本中经常出现的问题,因为当您说self.conn.send('Y'.encode()) self.conn仅指第二个播放器连接(我想这不是您打算做的) .

You should separate the conn in player1_conn and player2_conn and then you'll be able to chose to which player send what you need.您应该将player1_connplayer2_conn中的 conn 分开,然后您就可以选择向哪个玩家发送您需要的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM