Answer the question
In order to leave comments, you need to log in
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
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()
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 questionAsk a Question
731 491 924 answers to any question