在线游戏给出错误"("连接中止错误: [WinError 10053] "



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

("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:UsersZahraa RachedDesktopPoké-aimnetwork.py", line 25, in send
return pickle.loads(self.client.recv(4096))EOFError: Ran out of input

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

网络类:

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:

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)使用4096buf_size参数作为:

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

所以,这是最大值,而不是最小值。您的.recv()永远不会收到超过 4096 字节。就这样。

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

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

在您当前的网络设置中,某些东西导致较小的数据包到达recv(),而不是完全的"泡菜价值"。 这始终是网络通信的问题,可能是暂时的,也可能是永久性的。 也许潮湿的连接导致数据包丢失,也许也许。 它以前工作过,因为网络/计算机的行为不同。

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

整理数据结构以便通过网络发送可能是一种不错的方法,但我首先会传输酸洗对象的数据大小,以便接收客户端可以知道是否有足够的字节到达以解压缩它。 当然,你可以try..catch解腌制,但这效率极低。

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

编辑:有关结构等的更多详细信息。

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 servern" )
result = False
return result

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

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";)

无论如何,好的网络代码是处理所有的小粗糙边缘。 有时(出于一百种不同的原因(,数据不会到达大小合适的块中,或者您的网络块在一秒钟左右。 只需使用缓冲区和非阻塞代码来处理即可解决 99% 的弊病。

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

相关内容

最新更新