Как проиндексировать список без выбора? - PullRequest
0 голосов
/ 20 октября 2019

Я делаю шутер для многопользовательской арены в локальной сети, используя pygame и сокеты, и у меня возникают проблемы с передачей данных маринованных объектов с сервера на клиент. У меня есть 2 объекта, игрок и снаряд (патроны). Я не знаю, как отправить несколько объектов одновременно, поэтому я решил поместить 2 объекта в список и выбрать их. Но при снятии флажка я не могу индексировать список, так как получаю 'EOFError: Out out of input'

Так что я хочу снять список, который я получаю, и отделить 2 объекта в этом списке. Но python не позволит мне индексировать список после того, как я их выбрал. Любая помощь приветствуется. Вот мой код:

#instantiating instances for Player and Projectile classes

players=[Player(450,400,"sprite1.png",1),Player(500,400,"sprite2.png",2)]
bullets=[Projectile(50,50,5,"right","projectile.png",0)]  

def threaded_client(conn, player):
    player_data=(players[player])
    bullet_data=(bullets[player])
    alldata=[player_data,bullet_data]    #putting the 2 objects in a list.
    conn.send(pickle.dumps(alldata))     #pickling list

    reply = ""
    while True:
    try:
        alldata = pickle.loads(conn.recv(2048))
        players[player] = alldata[0]
...

self.client.connect(self.addr)
alldata=pickle.loads(self.client.recv(2048)) #unpickling the list
return alldata[0]   #trying to return the first object 

1 Ответ

1 голос
/ 20 октября 2019

Вы должны принять меры, чтобы убедиться, что у вас есть весь объект, прежде чем вы расстегните. Вы делаете conn.recv(XXX), но это не означает, что вы фактически получили все XXX байтов. В случае успеха это означает, что вы получили где-то от 1 до XXX байт (включительно). Если это небольшой буфер, вы часто получаете все это в одном куске, но вы никогда не должны рассчитывать на это.

Как правило, вы хотите отправить количество байтов в двоичном формате фиксированного размера (обычно с использованиеммодуль struct), затем после получения количества байтов продолжайте получать до тех пор, пока не получите все ожидаемые байты или не получите ошибку (т. е. ваш одноранговый узел отключен).

Что-то похожее на отправляющей стороне:

import struct

pickled_bytes = pickle.dumps(thing_youre_sending)
p_size = len(pickled_bytes)                # Size of pickled buffer
p_size_buf = struct.pack("!I", p_size)     # Packed binary size (4 byte field)
conn.sendall(p_size_buf)                   # Send length (Note sendall!)
conn.sendall(pickled_bytes)                # Send actual pickled object

На принимающей стороне вы будете делать что-то вроде этого:

import struct

...
def recv_all(conn, rlen):
    """ Function to receive all bytes """
    recvd = 0
    buf = b''
    while recvd < rlen:
        rbuf = conn.recv(rlen - recvd)
        if not rbuf:
            # Client disconnected. Handle error in whatever way makes sense
            raise ClientDisconnected()
        recvd += len(rbuf)
        buf += rbuf

...
p_size_buf = recv_all(conn, 4)                 # Receive entire binary length field
p_size = struct.unpack("!I", p_size_buf)[0]    # (Unpack returns an array)

pickled_bytes = recv_all(conn, p_size)         # Receive actual pickled object
thing_you_sent = pickle.loads(pickled_bytes)
...