简体   繁体   中英

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. 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.

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. 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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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