简体   繁体   English

如何在 python 中不等待地使用套接字

[英]How to use a socket without waiting in python

I create a game in Python, the game consists of several snakes each controlled by a different computer.我在 Python 中创建了一个游戏,该游戏由几条蛇组成,每条蛇由不同的计算机控制。 Each computer sends to the server computer the angle to which the snake is directed.每台计算机向服务器计算机发送蛇所指向的角度。

The problem is that the command问题是命令

client_mess = client_socket.recv(1024)

greatly inhibits server operation and causes the game to run very slowly.极大地抑制了服务器运行,导致游戏运行非常缓慢。 I am looking for a way to use the user message sent by the user, and if no message has been sent since the previous one the server will use the previous message and not wait for another message.我正在寻找一种使用用户发送的用户消息的方法,如果自上一个消息以来没有发送任何消息,服务器将使用上一个消息而不是等待另一条消息。

These are the relevant sections of my code:这些是我的代码的相关部分:

Server:服务器:

server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 5050))
server_socket.listen(1)
print("Server is up and running")

while not done:
    server_socket = socket.socket()
    server_socket.bind(('0.0.0.0', 5050))
    server_socket.listen(1)
    print("Server is up and running")

Client:客户:

while not done:
    
    for event in pygame.event.get():  # User did something
        if event.type == pygame.QUIT:  # If user clicked close
            done = True  # Flag that we are done so we exit this loop
    siz = type(siz)
    my_socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    my_socket.connect(('127.0.0.1', 5050))

    message = str(siz)

    my_socket.send(message.encode())

You can use sockets in non-blocking mode:您可以在非阻塞模式下使用 sockets:

import pygame as pg
import socket

pg.init()

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("localhost", 55555)) # Connect to server
client.setblocking(False) # Prevent socket from waiting for input

W, H = 640, 480
FLAGS = 0

screen = pg.display.set_mode((W, H), FLAGS)
W, H = screen.get_size()

font = pg.font.SysFont("arial", 30)

text = ""

running = True
while running:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False
        elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
            running = False

    try:
        raw = client.recv(1024)
    except BlockingIOError:
        pass # No new data. Reuse old data
    else:
        text = raw.decode("utf-8") # New data has arrived. Use it

    screen.fill((0, 0, 0))
    img = font.render(text, True, (255, 255, 255))
    r = img.get_rect(center=(W // 2, H // 2))
    screen.blit(img, r)
    pg.display.update()

This assumes a simple server script like this:这假设一个简单的服务器脚本是这样的:

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind(("localhost", 55555))
server.listen()

while True:
    client, address = server.accept()
    print("Connected to", address)
    while True:
        line = input("> ")
        try:
            client.send(line.encode("utf-8"))
        except ConnectionError as e:
            print(e)
            print("Disconnecting")
            client.close()
            break

It will display whatever line of text you entered on the server in the center of the pygame window.它将显示您在 pygame window 中心的服务器上输入的任何文本行。


If you want t he reverse situation, where the server has a pygame window open, you can use these pieces of code:如果你想要相反的情况,服务器有一个 pygame window 打开,你可以使用这些代码:

server:服务器:

import socket

import pygame as pg

pg.init()

W, H = 640, 480
FLAGS = 0

screen = pg.display.set_mode((W, H), FLAGS)
W, H = screen.get_size()

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 55556))
server.listen(1)
server.setblocking(False)
client = None

font = pg.font.SysFont("arial", 30)

text = ""

clock = pg.time.Clock()
running = True
while running:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False
        elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
            running = False
        elif event.type == pg.VIDEORESIZE:
            screen = pg.display.set_mode(event.size, FLAGS)
            W, H = screen.get_size()
    # Logic
    dt = clock.tick()

    if client is None:
        try:
            client, address = server.accept()
        except BlockingIOError:
            pass
    else:
        try:
            raw = client.recv(1024)
        except BlockingIOError:
            pass
        else:
            text = raw.decode("utf-8")


    # Render
    screen.fill((0, 0, 0))
    img = font.render(text, True, (255, 255, 255))
    r = img.get_rect(center=(W // 2, H // 2))
    screen.blit(img, r)

    pg.display.update()
    pg.display.set_caption(f"FPS: {clock.get_fps():.2f}")

client客户

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client.connect(("localhost", 55556))

try:
    while True:
        line = input("> ")
        try:
            client.send(line.encode("utf-8"))
        except ConnectionError as e:
            print(e)
            print("Disconnecting")
            break
finally:
    client.close()

If you want both to have pygames windows, I would suggest considering using multiple clients and one non-pygame server instead.如果您希望两者都拥有 pygames windows,我建议您考虑使用多个客户端和一个非 pygame 服务器。 But similar code should work anyway.但是无论如何,类似的代码应该可以工作。

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

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