在线游戏报错“("ConnectionAbortedError: [WinError 10053] " [英] Online game give the error "("ConnectionAbortedError: [WinError 10053] "

查看:108
本文介绍了在线游戏报错“("ConnectionAbortedError: [WinError 10053] "的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用 pygame 和 socket 用 python 制作了一个游戏,我的游戏在本地服务器上运行良好,但是当我想和我的朋友一起尝试时,它给了我这些错误:

I made a game in python with pygame and socket, my game works perfectly in local server, but when i want to try it with my friend it give me these errors :

("ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

   Traceback (most recent call last
File "C:/Users/Zahraa Rached/Desktop/Poké-aim/client.py", line 54, in <module>
   game = n.send("get")
 File "C:\Users\Zahraa Rached\Desktop\Poké-aim\network.py", line 25, in send
   return pickle.loads(self.client.recv(4096))EOFError: Ran out of input

我的端口被转发了,我已经玩了一个我在不同电脑上编码的游戏(和我的朋友)所以问题不应该是我的服务器主机(我尝试了很多不同的方法,例如禁用防火墙和防病毒软件)

My port are frowarded and i arleady played a game that i have coded on different pc (with my friends) so the problem should not be my server host (i tried a lot of different things like disabling my firewall and my antivirus)

网络类:

class Network:
    def __init__(self):
        self.client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.server="my public ip"
        self.port=50
        self.addr=(self.server,self.port)
        self.p=self.connect()

    def getP(self):
        return self.p
    def connect(self):
        try:
            self.client.connect(self.addr)
            return self.client.recv(4096).decode()
        except:
            pass

    def send(self,data):
        try:
            self.client.send(str.encode(data))

            return pickle.loads(self.client.recv(4096))
        except socket.error as e:
            print(e)

服务器



import socket
from _thread import*
import pickle
from game import*

g=Game()
clientnb=0
server="192.168.1.43"
port=50
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)


try:

    s.bind((server,port))
except socket.error as e:
    print(e)

s.listen()
print("J'attend une connexion, Dresseur de Pokémon")
def thread(conn,p):
    global clientnb
    global g
    print(clientnb)
    g.pos[p]=(0,0)

    conn.send(str.encode(str(p)))
    r=False

    reply=""
    while True:
        if g.ready == clientnb and clientnb > 1:
            g.start=True
        else:
            g.start=False
        try:
            data=conn.recv(4096).decode()
            if data=="ready":
                r=True
                g.ready+=1
            elif data=="clik":
                    print("x")
                    print(g.ball)
                    g.changepos()
                    g.changeball()
                    print(g.ball)
            elif data=="reset":
                g.reset()
            elif data=="win":
                g.end=True


            elif data!="get":

                co=eval(data)
                g.pos[p]=co

            elif not data:
                print("oh")
                if r:
                    g.ready-=1
                clientnb-=1
                del g.pos[p]
                break


            reply = g
            conn.sendall(pickle.dumps(reply))
        except:
            print("ohh")
            if r:
                g.ready -= 1
            clientnb -= 1
            g.reset()
            break
    conn.close()
while True:
    conn,addr=s.accept()
    print(addr)
    p = clientnb
    start_new_thread(thread,(conn,p))

    clientnb+=1

客户:


import pygame
import pickle
import sys
from network import Network
import time
import socket
pygame.font.init()

pygame.mixer.pre_init(44100, -16, 2, 512)
pygame.mixer.init()
pygame.init()
run=True
timevar=False
pygame.mixer.music.load("music.mp3")
pygame.mixer.music.set_volume(0.1)
myscore=0
w=1280
h=720
screen= pygame.display.set_mode((w,h))
pygame.display.set_caption("Poké-Aim")
n=Network()
fond_color=(0,0,0)
color1 = (255, 0, 0)
click=pygame.mixer.Sound("click.ogg")




ball=pygame.transform.scale(pygame.image.load("ball.png").convert_alpha(),(71,62))
master=pygame.transform.scale(pygame.image.load("master.png").convert_alpha(),(35,31))
bigmaster=pygame.transform.scale(pygame.image.load("master.png").convert_alpha(),(71,62))
cursor=pygame.transform.scale(pygame.image.load("cursor.png").convert_alpha(),(48,48))
other_cursor=pygame.transform.scale(pygame.image.load("black_cursor.png").convert_alpha(),(48,48))
playing=False
loosing=False
winning=False
def find_key(v):
    for k, val in pos.items():
        if v == val:
            return k

clock=pygame.time.Clock()

ready=False
start=False
p=int(n.getP())
print(p)
pygame.mouse.set_visible(False)
while run:

    clock.tick(60)
    screen.fill(fond_color)
    try:
        game = n.send("get")

    except socket.error as e:
        print(e)
        run=False
        print("Connexion perdue")
        break
    if game!=None:
        start=game.start
        name=game.name
        bol=game.ball
        pos=game.pos
        end=game.end
        if game.ready==0:
            ready=False
    if not start:
        if not ready:
            color1=(255,0,0)
        font = pygame.font.Font("Pokemon Classic.ttf", 20)
        sc=font.render("= 1 pts", 1,(255,255,255) )
        sc2=font.render("= 3pts", 1,(255,255,255) )
        screen.blit(sc,(w/2,150))
        screen.blit(sc2, (w / 2, 215))
        screen.blit(ball,((w/2-80),140))
        screen.blit(bigmaster, ((w / 2 - 80), 200))

        text = font.render("Clique sur l'écran pour te mettre prêt !", 1,color1 )

        screen.blit(text, ((w - text.get_width()) / 2, (h - text.get_height()) / 2))
    elif start:

        screen.fill((255,244,10))
        if not playing:
            pygame.mixer.music.play()
            playing=True
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                while not ready and not timevar:

                    color1 = (0,255, 0)

                    screen.blit(text, ((w - text.get_width()) / 2, (h - text.get_height()) / 2))
                    n.send("ready")
                    click.play()
                    ready=True
                if start:
                    if name=="P":
                        if (bol[0]) <= (pygame.mouse.get_pos()[0] ) <= (bol[0] + 71):
                            if pygame.mouse.get_pos()[1]>= (bol[1]) and pygame.mouse.get_pos()[1] <= (bol[1] + 62):
                                click.play()
                                n.send("clik")
                                click.play()
                                myscore+=1
                    else:
                        if (bol[0]) <= (pygame.mouse.get_pos()[0] ) <= (bol[0] + 35):
                            if (pygame.mouse.get_pos()[1]) >= (bol[1]) and (pygame.mouse.get_pos()[1] )<= (bol[1] + 31):
                                click.play()
                                n.send("clik")
                                myscore+=3

    try:
        n.client.send(str.encode(str(pygame.mouse.get_pos())))
    except :
        pass

    if start:
        if name=="P":
            screen.blit(ball, (bol[0], bol[1]))
        else:
            screen.blit(master, (bol[0], bol[1]))



        for e in pos.values():
            if find_key(e) != p:
                if find_key(e) != p:
                    screen.blit(other_cursor, (e[0]-24,e[1]-24))



    score = font.render(str(myscore), 1, (0,0,0))
    screen.blit(score, (5,0))
    if myscore >= 1:

        pygame.mixer.music.stop()

        screen.fill((0, 0, 0))
        wintext = font.render("T'as gagné sale bg !", 1, color1)
        screen.blit(wintext, ((w - wintext.get_width()) / 2, (h - wintext.get_height()) / 2))






        pygame.display.update()
        n.send("win")
        if not timevar:
            chrono=time.time()
            timevar=True
        if round(time.time()-chrono)>4:
            n.send("reset")

            color1 = (255, 0, 0)
            start = False
            ready = False
            playing = False
            myscore = 0
            timevar=False

            end = False
    elif end:

        pygame.mixer.music.stop()

        screen.fill((0, 0, 0))
        loosetext = font.render("T'as perdu t'es trop nul sérieux !", 1, (255,0,0))
        screen.blit(loosetext, ((w - loosetext.get_width()) / 2, (h - loosetext.get_height()) / 2))

        pygame.display.update()

        if not timevar:
            chrono = time.time()
            timevar = True
        if round(time.time() - chrono) > 4:

            color1 = (255, 0, 0)
            start = False
            ready = False
            playing = False
            myscore = 0
            timevar = False

            end = False




    screen.blit(cursor,(pygame.mouse.get_pos()[0]-24,pygame.mouse.get_pos()[1]-24))
    pygame.display.update()

game_class:

game_class:

import random
h=720
w=1280
class Game:
    def __init__(self):
        self.name="P"
        self.pos= {}
        self.ball=[w/2,h/2]
        self.ready=0
        self.start=False
        self.end=False
    def changepos(self):
        if self.name=="P":
            self.ball[0]=random.randrange(0+71,w-71)
            self.ball[1]=random.randrange(0,h-62)
        else:
            self.ball[0] = random.randrange(0 + 35, w- 35)
            self.ball[1] = random.randrange(0, h - 31)
    def changeball(self):
        self.name=random.choice("MPPPPPPPPPP")
    def reset(self):
        self.name = "P"

        self.ball = [w / 2, h / 2]
        self.ready=0

        self.start = False
        self.end = False

推荐答案

快速阅读 手册关于socket.recv() 告诉我们self.client.recv(4096) 使用4096 buf_size 参数为:

A quick read of the manual about socket.recv() tells us that self.client.recv(4096) uses that 4096 buf_size parameter as:

一次接收的最大数据量由 [...] 指定

The maximum amount of data to be received at once is specified by [...]

所以,这是最大值,而不是最小值.您的 .recv() 永远不会收到超过 4096 个字节.仅此而已.

So, it's the maximum, not the minimum. Your .recv() will never receive more than 4096 bytes. That's all.

但是代码假设它总是 recv() 足够的字节:

But the code is assuming it will always recv() enough bytes:

return pickle.loads( self.client.recv(4096) ) # gambling a crash on Rx size

在您当前的网络设置中,某些原因导致较小的数据包到达 recv(),而不是完整的pickle-worth".这始终是网络通信的问题,可能是暂时的,也可能是永久性的.也许潮湿的连接导致数据包丢失,也许也许.因为网络/计算机的行为不同,所以以前可以正常工作.

On your current network set-up, something is causing smaller packets to arrive at the recv(), and not a full "pickle-worth". This is always an issue with network communications, it may be temporary, it may be permanent. Maybe a damp connection is causing packet loss, maybe maybe maybe. It was working before because the network/computers behaved differently.

那你怎么办?解决方案是检查是否有任何字节到达.如果 字节已到达,则将它们添加到传入缓冲区".如果缓冲区中有足够的字节,则将其解包.

So what do you do? The solution is check to see if any bytes have arrived. If bytes have arrived, add them to an "incoming-buffer". If there's enough bytes in the buffer, unpack it.

pickling 用于通过网络发送的数据结构可能是一个不错的方法,但我会首先传输pickled 对象的数据大小,因此接收客户端可以知道是否已到达足够的字节来解包它.当然你可以try..catch un-pickling,但这非常低效.

Pickling a data structure for sending over the network is probably an OK method, but I would first transmit the data-size of the pickled object, so the receiving client can know whether enough bytes have arrived to unpack it. Sure you can try..catch the un-pickling, but that's grossly inefficient.

我会使用 struct.pack 将泡菜缓冲区大小作为 4 字节整数(以网络字节顺序)发送.首先接收这 4 个字节,然后等待进一步的 N 个字节到达.

I would use struct.pack to send the pickle-buffer size as a 4-byte integer (in network-byte order). Receive those 4 bytes first, then wait for the further N bytes to arrive.

有关结构等的更多详细信息

import struct
import pickle

def sendData( server_sock, object ):
    result = True
    data = pickle.dumps( object )
    data_size = struct.pack( '!I', len( data ) )  # good for 2^32 bytes

    try:
        server_sock.sendall( data_size )   # send the size of the pickled obj
        server_sock.sendall( data )        # send the obj
    except:
        sys.stderr.write( "Error sending data to server\n" )
        result = False
    return result

然后接收数据,读取4字节大小的字段,然后是pickle数据.像下面这样的东西应该可以工作(注意:这不是经过测试的代码,我只是在回答)

And then to receive the data, read the 4-byte size field and then the pickle data. Something like the below should work (note: this is not tested code, I'm just answering off the top of my head)

def recvData( client_sock ):
    """ Try to receive a picked data-structure from the socket.
        Returns True and an unpicked object, or False and None   """
    result   = False
    packet   = None
    expected = -1

    # First we read a 4-byte pickle size, and following that is /N/ bytes
    # of pickled structure data.

    # Read the 4-byte packet size first
    buffer = bytes()
    while ( len( buffer ) < 4 ):
        try:
            some_data = client_sock.recv( 4 - len( buffer ) )
            if ( some_data ):
                 buffer.append( some_data )
                 if ( len( buffer ) == 4 ):
                     expected = struct.unpack( '!I', buffer )
        except:
            # TODO: work out which sort of exceptions are OK
            break

    # If we received a buffer size, try to receive the buffer
    if ( expected > 0 ):
        buffer = bytes()
        while ( len( buffer ) < expected ): 
            try:
                some_data = client_sock.recv( expected - len( buffer ) )
                if ( some_data ):
                     buffer.append( some_data )
                     # Have we received the full data-set yet?
                     if ( len( buffer ) == expected ):
                         packet = pickle.loads( buffer )
                         result = True   # success
        except:
            # TODO: work out which sort of exceptions are OK
            break

     return result, packet

老实说,如果您只是一直发送固定数量的数据(例如一对 x/y 坐标),那么使用固定大小的数据报打包和解包所有内容可能会更容易.也许这还不够pythonic";)

To be honest if you're just sending fixed amounts all the time (like a pair of x/y co-ordinates), it might be easier to just pack and unpack everything, using fixed-size datagrams. Maybe that's not "pythonic" enough though ;)

无论如何,良好的网络代码是处理所有的小毛边.有时(出于一百种不同的原因),数据不会以大小合适的块或网络块的形式到达一秒钟左右.只需使用缓冲区处理这个问题,非阻塞代码就可以解决 99% 的问题.

Anyway, what makes good network code is handling all the little rough edges. Sometimes (for a hundred different reasons), data does not arrive in nicely sized blocks, or your network blocks for a second or so. Simply handling this with a buffer, and non-blocking code solves 99% of the ills.

实际上,上面的 recv() 应该是非阻塞代码,但这留给读者作为练习.我喜欢为此使用 select() ,但这有点过时.

Really the recv() above should be non-blocking code, but this is left as an exercise for the reader. I like to use select() for this, but that's a bit old-fashioned.

这篇关于在线游戏报错“("ConnectionAbortedError: [WinError 10053] &quot;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆