Bug socket linux windows
RésoluBonjour,
Je suis en train de créer un jeu en ligne via le module socket.
Quand je lance le serveur et 2 clients depuis mon ordinateur windows ça marche.
Mais quand je lance n'importe quel programme (serveur ou client) depuis mon ordinateur linux, l'application ne marche pas (erreur -> json decode error ou aucune erreur et le programme attend)
Voici mon code:
server.py
import socket import threading import json import random class Server: def __init__(self, addr, port): self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.bind((addr, port)) self.CARTES = (0, 1) self.GEARS = (0, 1) self.ok_message = "OK!" self.nope_message = "NOPE!" self.DECO = "DECO!" self.games = {} self.names = {} self.map_ok = {} self.map = {} self.gear_ok = {} self.gear = {} def start(self): self.server.listen() while True: conn, _ = self.server.accept() threading.Thread(target=self.handle_client, daemon=True, args=(conn, )).start() @staticmethod def recv(conn): inf = conn.recv(1024).decode() print(inf) try: return json.loads(inf)[0] except json.decoder.JSONDecodeError: return json.loads(repr([inf, ])) @staticmethod def send(conn, msg): conn.send(json.dumps([msg,]).encode()) def handle_client(self, conn): # get username while True: username = self.recv(conn) if username in self.names.values(): self.send(conn, self.nope_message) else: self.send(conn, self.ok_message) self.names[conn] = username break # get type_game type_game = self.recv(conn) if not self.games.get(type_game, False): self.games[type_game] = [conn, ] else: self.games[type_game].append(conn) # get game while True: id_game = len(self.games[type_game]) while len(self.games[type_game]) < 2: pass if id_game == 1: opp = self.games[type_game][id_game] break elif id_game == 2: opp = self.games[type_game][id_game - 2] break self.send(conn, self.ok_message) self.recv(opp) self.games[type_game].pop(self.games[type_game].index(conn)) self.send(conn, [id_game, self.names[opp]]) # get map carte = None while carte not in self.CARTES: carte = self.recv(conn) if carte in self.CARTES: self.send(conn, self.ok_message) self.map[conn] = carte break else: self.send(conn, self.nope_message) if id_game == 1: if self.map_ok.get((conn, opp)) is None: self.map_ok[(conn, opp)] = [True, False] else: self.map_ok[(conn, opp)] = [True, True] while not all(self.map_ok[(conn, opp)]): pass carte = random.choice([self.map[conn], self.map[opp]]) self.send(conn, carte) self.send(opp, carte) else: if self.map_ok.get((opp, conn)) is None: self.map_ok[(opp, conn)] = [True, False] else: self.map_ok[(opp, conn)] = [True, True] # gear print("GETTING GEAR") gear = None while gear not in self.GEARS: gear = self.recv(conn) ok = True for g in gear: if g not in self.GEARS: ok = False break if ok: self.send(conn, self.ok_message) self.gear[conn] = gear break else: self.send(conn, self.nope_message) if id_game == 1: if self.gear_ok.get((conn, opp)) is None: self.gear_ok[(conn, opp)] = [True, False] else: self.gear_ok[(conn, opp)] = [True, True] while not all(self.gear_ok[(conn, opp)]): pass print(self.gear[opp], self.gear[conn]) self.send(conn, self.gear[opp]) self.send(opp, self.gear[conn]) else: if self.gear_ok.get((opp, conn)) is None: self.gear_ok[(opp, conn)] = [True, False] else: self.gear_ok[(opp, conn)] = [True, True] # game while True: msg = self.recv(opp) self.send(conn, msg) if __name__ == "__main__": server = Server("localhost", 5070) server.start()
game.py
from networking import Client import game import pygame def test(addr, port): x = y = x2 = y2 = 100 j_moi = pygame.Surface((50, 50)) j_moi.fill((255, 0, 0)) j_opp = pygame.Surface((50, 50)) j_opp.fill((0, 0, 255)) clock = pygame.time.Clock() aff_win = True run = True with Client(addr, port) as client: # get some info name = input("Entrer un nom d'utilisateur: ") while not client.get_username(name): print("nom deja utilise!") name = input("Entrer un nom d'utilisateur: ") moi_aff = game.Afficher((0, 0), name, (0, 0, 0), 30) id_game, opp = client.get_game("!PUBLIC") print("id_game:", id_game) print("opp:", opp) opp_aff = game.Afficher((0, 0), opp, (0, 0, 0), 30) while True: carte_inp = input("Entrer une carte: ") try: carte_inp = int(carte_inp) - 1 except ValueError: print("Entrer le nombre de la carte!") continue carte = client.get_map(carte_inp) if carte is not None: break print("map n'existe pas!") print("carte:", carte) # gear while True: gear = [] for i in range(game.GEAR_LEN): while True: inp = input("Entrer gear "+str(i + 1)+": ") try: inp = int(inp) - 1 break except ValueError: print("Veuillez entrer le nombre du gear que vous voulez utiliser!") gear.append(inp) gear_opp = client.get_gear(gear) if gear_opp is not None: break print("gear n'existe pas!") print("gear opp:", gear_opp) # game pygame.init() screen = pygame.display.set_mode((game.width, game.height)) pygame.display.set_caption(name) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False aff_win = False break if not run: break key = pygame.key.get_pressed() if key[pygame.K_UP]: y -= game.base_J_DEP[0] if key[pygame.K_DOWN]: y += game.base_J_DEP[0] if key[pygame.K_LEFT]: x -= game.base_J_DEP[0] if key[pygame.K_RIGHT]: x += game.base_J_DEP[0] info = client.dialogue([x, y]) if len(info) == 1: if info == client.DECO: print("L'ADVERSAIRE C'EST DÉCONNECTER!!!!!") run = False elif len(info) == 2: x2, y2 = info moi_aff.update(x=x + moi_aff.surface.get_width()//2, y=y - moi_aff.surface.get_height()) opp_aff.update(x=x2 + opp_aff.surface.get_width()//2, y=y2 - opp_aff.surface.get_height()) screen.fill((255, 255, 255)) screen.blit(j_moi, (x, y)) screen.blit(j_opp, (x2, y2)) moi_aff.draw(screen) opp_aff.draw(screen) pygame.display.update() clock.tick(60) if __name__ == "__main__": addr = input("Entrer l'address: ") while True: port = input("Entrer le port: ") try: port = int(port) break except ValueError: print("Veuillez entrer un nombre entier pour le port.") test(addr, port)
dossier networking:
__init__.py
from .client import *
client.py
import socket import json class Client: def __init__(self, addr, port): self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client.connect((addr, port)) self.DECO = "DECO!" self.ok_message = "OK!" self.nope_message = "NOPE!" def send(self, msg): print("sending:", msg) self.client.send(json.dumps([msg]).encode()) def recv(self): infos = self.client.recv(1024).decode() print(infos) return json.loads(self.client.recv(1024).decode())[0] def dialogue(self, msg): self.send(msg) return self.recv() def __enter__(self): return self def __exit__(self, *_): self.send(self.DECO) def get_game(self, msg): self.dialogue(msg) return self.dialogue(self.ok_message) def get_username(self, msg): return self.dialogue(msg) == self.ok_message def get_map(self, msg): self.send(msg) if self.recv() == self.ok_message: return self.recv() def get_gear(self, msg): self.send(msg) if self.recv() == self.ok_message: return self.recv()
le dossier game:
__init__.py
from .sprite import Sprite from .afficher import Afficher from .get_path import path, separator from .data import *
sprite.py
import pygame class Sprite: __list = [] @classmethod def get_list(cls): return cls.__list def __init__(self, coord: (int, int), surface: pygame.Surface): self.alive = True self.show = True self.x, self.y = coord self.surface = surface self.mask = pygame.mask.from_surface(self.surface) self.__list.append(self) self.nb = len(self.__list) self.nom = "Sprite{}".format(self.nb) def draw(self, screen: pygame.Surface): if self.alive and self.show: screen.blit(self.surface, (self.x, self.y)) def is_coliding(self, m): if m == "all": check = self.__list check.remove(self) elif type(m) == tuple or type(m) == list or m is None: check = m if m == () or m == [] or m is None: return elif hasattr(m, "mask") and hasattr(m, "x") and hasattr(m, "y"): check = (m,) else: raise (ValueError("parameter m is not valid, please enter \"all\" " "or a Mask or a tuple/list of Mask: not a {}".format(type(m)))) res = [] for sprite in check: if self.mask.overlap_mask(sprite.mask, (sprite.x - self.x, sprite.y - self.y)).count() != 0: try: if sprite.alive: res.append(sprite) except AttributeError: res.append(sprite) return res def __str__(self): return self.nom def __repr__(self): return "{}->x:{},y:{}".format(self.nom, self.x, self.y) def check_alive(self): if not self.alive: self.__list.remove(self) def update(self): self.check_alive()
afficher.py
from .sprite import Sprite from .get_path import path import pygame class Afficher(Sprite): def __init__(self, coord, texte, color, taille): police = pygame.font.Font(path+"arial_narrow_7.ttf", taille) texte_surface = police.render(texte, True, pygame.Color(color)) super().__init__(coord, texte_surface) self.texte = texte self.taille = taille self.color = color self.nom = "Afficher{}".format(self.nb) def update(self, texte=None, x=None, y=None): if texte is not None: police = pygame.font.Font(path+"arial_narrow_7.ttf", self.taille) self.surface = police.render(texte, True, pygame.Color(self.color)) if x is not None: self.x = x if y is not None: self.y = y self.check_alive()
get_path.py
import os import sys separator = "/" if sys.platform == "linux" else "\\" path = __file__.split(separator) path = path[:-1] _ = "" for p in path: _ += p + (separator) path = _
data.py
import pygame from .get_path import path from .mur import Mur pygame.init() width, height = pygame.display.Info().current_w - 70, pygame.display.Info().current_h - 70 maps = [{"mur": [Mur(0, -100, width, 100), Mur(width, 0, 100, height), Mur(0, height, width, 100), Mur(-100, 0, 100, height), Mur(-100, 0, 100, height), Mur(width // 7, height // 3.3, 30, width // 4.5), Mur(width // 7 * 6, height // 3.3, 30, width // 4.5), Mur(width // 2 - 15, 0, 30, height // 6 + 10), Mur(width // 2 - 15, height // 6 * 5, 30, height // 6 + 10)]}, ] GEAR_LEN = 8 WH_PLAYER = 100 WH_TIR = 10 base_J_DEP = (10, 3) base_J_VIE = 100 base_TIR_DEP = (15, 3) base_TIR_DEGAT = 3 base_background = pygame.image.load(path + "space.png") base_background = pygame.transform.scale(base_background, (width, height)) base_j1_image = pygame.image.load(path + "wizard_bleu.png") base_j1_image = pygame.transform.scale(base_j1_image, (WH_PLAYER, WH_PLAYER)) base_j1_image.set_colorkey((255, 255, 255)) base_j1_image_wand = pygame.image.load(path + "wand_bleu.png") base_j1_image_wand = pygame.transform.scale(base_j1_image_wand, (WH_PLAYER, WH_PLAYER)) base_j1_image_wand.set_colorkey((255, 255, 255)) base_j2_image = pygame.image.load(path + "wizard_rouge.png") base_j2_image = pygame.transform.scale(base_j2_image, (WH_PLAYER, WH_PLAYER)) base_j2_image.set_colorkey((255, 255, 255)) base_j2_image_wand = pygame.image.load(path + "wand_rouge.png") base_j2_image_wand = pygame.transform.scale(base_j2_image_wand, (WH_PLAYER, WH_PLAYER)) base_j2_image_wand.set_colorkey((255, 255, 255)) base_j1_image_tir = pygame.Surface((WH_TIR, WH_TIR)) base_j1_image_tir.fill((0, 0, 255)) base_j2_image_tir = pygame.Surface((WH_TIR, WH_TIR)) base_j2_image_tir.fill((255, 0, 0))
(-> jeu pas fini)
(pour ce qui veulent tester le jeu pour m'aider il faut aller télécharger la police arial narrow7.ttf.
Je pense que les erreurs viennent de socket.
J'ai essayé cette commande (sur linux) lorsque je cherchais une solution:
sysctl -w net.ipv4.tcp_timestamps=0
Rien n'a changé. Si vous n'avez pas tout compris, posez des questions et merci de m'aider à résoudre mon problème,
Flayme
- Bug socket linux windows
- Clé windows 8 - Guide
- Montage video windows - Guide
- Windows ne démarre pas - Guide
- Windows movie maker - Télécharger - Montage & Édition
- Restauration systeme windows 10 - Guide
4 réponses
Bonjour,
Merci quand tu partages de préciser dans la cellule de code le langage de programmation (python).
Autant que possible, évite de mettre tout ton programme pour parler d'un problème précis. Il faut plutôt construire un exemple minimal qui met en évidence le problème, nous expliquer comment tu le lances, le comportement observé et le comportement attendu. Ici une grande partie du code partagé n'a vraisemblablement rien à avoir avec ton problème.
Vu que le projet est volumineux et contient des ressources qui ne sont pas du code (polices, images...) il vaudrait mieux mettre ton projet par exemple sur github et nous donner l'adresse du dépôt. Car là, il manque des fichiers pour tester ton code.
Je te propose de repartir sur cet exemple relativement minimal qui montre comment écrire en pygame un jeu multijoueur ou chaque joueur peut depuis sont client déplacer un carré qui lui est propre et voir le carré des autres joueurs.
Bonne chance
Salut, si tu souhaites avoir de l'aide afin d'identifier ce qui cloche, fais un zip de ton application que tu hébergeras quelque part afin que l'on ait pas à copier/coller chacun de tes codes dans chaque fichier, et surtout que l'on a juste à lancer ton programme pour pouvoir le déboguer, et si possible réduire au minimum ton script, il n'y a certainement pas besoin de tout ces fichiers, essaie d'identifier celui où cela bogue, client, serveur, et json, pas besoin de pygame et tous ces packages.
Sinon, comme d'habitude, des prints, des exceptions pour comprndre où ton programme plante. Déjà je vois un ÉNORME problème, c'est que tu as un fichier game, et un package game, nomme les différemment ! Même si ça fonctionne en l'état.
Bon courage.
Pour corriger mon bug, j'ai encadré tout mes messages avec un caractère: "^" ce qui permet de savoir exactement ou commence et ou finit le message pour ne pas avoir d'interférence. Avant cela, il faut vérifier si le caractère est dans le message pour éviter les problèmes.
Je ne sais pas comment on fait pour marquer résolu ma question, donc si un modérateur pouvait le faire pour moi ce serait gentil.
Merci quand même d'avoir essayer de m'aider
Au revoir
Flayme
Pour marquer une discussion en résolu, il faut faire comme expliqué dans ce lien, mais cela nécessite d'avoir un compte CCM. Bref, je m'en occupe.
Concernant ton problème, je reste un peu sceptique sur la manière dont tu l'as résolu. Voici un petit exemple qui met en évidence un client qui envoie chaque seconde une chaîne de caractère à 5 reprises vers un serveur qui réécrit le message reçu sur sa sortie standard. Comme tu peux le voir, il n'y a pas de délimiteur impliqué dans le code.
- server.py
import socket SERVER_BIND_ADDRESS = "localhost" SERVER_PORT = 8000 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server: print(f"Starting server {SERVER_BIND_ADDRESS}:{SERVER_PORT}") server.bind((SERVER_BIND_ADDRESS, SERVER_PORT)) server.listen() (client, client_addr) = server.accept() with client: print(f"New client {client_addr}") while True: data = client.recv(1024) # Fetch the data, 1024 bytes by 1024 bytes if not data: break # No more data to fetch message = data.decode("utf-8") print(message)
- client.py
import socket from time import sleep SERVER_HOST = "localhost" # The server's hostname or IP address SERVER_PORT = 8000 # The port used by the server with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client: print(f"Connect to {SERVER_HOST}:{SERVER_PORT}") client.connect((SERVER_HOST, SERVER_PORT)) for i in range(5): client.sendall(bytes(f"Hello, world {i}", "utf-8")) sleep(1)
- Utilisation
- Lancer server.py dans un terminal
- Puis lancer client.py dans un autre terminal
- Résultat (terminal server.py)
Starting server localhost:8000
New client ('127.0.0.1', 60514)
Hello, world 0
Hello, world 1
Hello, world 2
Hello, world 3
Hello, world 4
Bonne continuation.