Y
Y
Yourmind2019-07-25 03:48:49
Python
Yourmind, 2019-07-25 03:48:49

Interaction of two hosts in a network game?

I am writing the server side of the checkers game.
There are 2 clients. Each client can start a new game button, exit or continue walking. If he moves, then the order is checked: white or black move. And any of them can always press the button for a new game or close. And now I don’t understand: how to make sure that we can “hear” the signal from one and the other at once and not in turn?

import pickle
import socket

what_colour_now='white'
sock = socket.socket()
sock.bind(('', 9090))
sock.listen(2) #accept
connections for two hosts
conn1, addr1 = sock.accept()
conn2, addr2 = sock.accept()

while True: #what
one of the players sent
#and here is the problem! how to make it so that we, regardless of their order, could respond to the new game and close buttons. it’s just that if I write like here, then we first wait for what the first host will say and then react to the second one. and if, for example, the first one will think for a long time that the second one simply won’t be able to send us anything. What if he wanted to start a new game or quit? that is, how to make sure that we react to these 2 events immediately?
data1 = conn1.recv(1024)
data2 = conn2.recv(1024)

if not data:
break

f=pickle.loads(data)

conn2.close()
conn1.close()

Answer the question

In order to leave comments, you need to log in

2 answer(s)
K
Kapustlo, 2019-07-25
@Kapustlo

Good day, in principle 66demon666thought correctly, but, unfortunately, did not tell about the practical side. I suggest you take advantage of the higher-level, standard Python "socketserver" module, which makes it easier to implement servers that run over UDP and TCP protocols. And so, speaking about setting up the server, we will need to initially create a request handler, a class that will inherit from the "socketserver.BaseRequestHandler" class. In our newly created class, we need to override the "handle" method, which does nothing by default, so that we can process incoming requests. Next, we create our server class with multiple inheritance, in which at this stage we will not add our own methods and will not override the existing ones. Next, I will go a little deeper and tell you a little about my opinion about the organization of the gameplay. I suggest creating two classes for now: "Player" and "Session". "Session" will inherit our TCP server and in its "__init__" method will assign itself to the event handler so that we can safely operate session data from it. Actually, the "Player" class was added in order to simplify the work with the data of the players, so as not to create dictionaries with their data and so on. In principle, I believe that my explanations are over, the rest you will see in the code. so that we can safely operate session data from it. Actually, the "Player" class was added in order to simplify the work with the data of the players, so as not to create dictionaries with their data and so on. In principle, I believe that my explanations are over, the rest you will see in the code. so that we can safely operate session data from it. Actually, the "Player" class was added in order to simplify the work with the data of the players, so as not to create dictionaries with their data and so on. In principle, I believe that my explanations are over, the rest you will see in the code.

import socket
import threading
import socketserver

class Player:
    def __init__(self, id, name):
        self.id = id
        self.name = name

class TCPRequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        encoding = "utf-8"

        data = self.request.recv(1024)

        # Дальше мы обрабатываем данные, которые пришли и, например, создаём из них словарь
        if len(session.get_players()) < 2:
            player = Player(data["id"], data["name"])
            session.add_player(player)
            self.request.send("Some response".encode(encoding))
        else:
            self.request.send("Some error data".encode(encoding))

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

class Session(ThreadedTCPServer):
    def __init__(self, connection_data, request_handler):
        super().__init__(connection_data, request_handler)

        self.max_players = 2
        self.players = {}
        self.over = False

        request_handler.session = self

    def get_players(self):
        return self.players

    def add_player(self, player):
        if type(player) == Player:
            if len(self.players) < self.max_players:
                self.players[player.id] = player
            else:
                raise Exception("Players overflow")
        else:
            raise TypeError("'player' argument must be a 'Player' type")

    def game_over(self):
        self.over = True

if __name__ == "__main__":
    HOST, PORT = "localhost", 80

    session = Session((HOST, PORT), TCPRequestHandler)

    with session:
        session_thread = threading.Thread(target=session.serve_forever)

        session_thread.daemon = True
        session_thread.start()

        while not session.over:
            pass # Заглушка, чтобы сервер работал

        session.shutdown()

M
Mors Clamor, 2019-07-25
@66demon666

Well, but somehow, everything is done in one thread, until one operation is completed, another does not start. Look for a way to split into 2 threads,
But honestly, I would have done it differently. There is one function that listens to any requests from any clients, and as parameters it takes the client identifier (to distinguish one from the other) and the actual parameters of what we want to do. For example
Function listen(action, parameters)
If action=="new game"
...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question