Home > Back-end >  How can I receive multiple lists form server with python socket?
How can I receive multiple lists form server with python socket?

Time:10-03

I made a very simple server and client program to test. I need to send 3 different lists from server and client must recieve them seperately. Could you please help me ?

Here is server.py

import socket
import pickle

am0=['AQ-20', 'A3000', 'AQ-26', 'A5000', 'AQ-33', 'A5000pro', 'AQ-33pro']
am1=['A10000Pro', 'AQ-43', 'AX-48', 'AX-58', 'AX-68']
am2=['Material', 'nan', 'Steel', 'Stainless S.', 'Stainless S. 1.403']

am00=pickle.dumps(am0)
am01=pickle.dumps(am1)
am02=pickle.dumps(am2)

mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket.bind(('127.0.0.1', 1))
buffer_size = 1024
mysocket.listen()
(client, (ip,port)) = mysocket.accept()
client.send(am00)

#----------------HOW CAN I ADD THEM:----------------
#client.send(am01) 
#client.send(am02)

mysocket.close()

here is client.py

import socket
import pickle

host = '127.0.0.1'
port = 1
buffer_size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

#----------------HOW CAN I RECEIVE THEM SEPERATELY ?----------------
data1 = pickle.loads(s.recv(buffer_size))
print(data1)

CodePudding user response:

the pickle protocol includes the length of the pickled buffer and you can use pickle.Unpickler to load one pickled object at a time. The problem is that it wants a file-like object, not a socket. Fortunately, sockets can make themselves look like files using socket.makefile. There are caveats, so reading the referenced doc is worthwhile.

Update your server to write each pickled object and then change the client to

import socket
import pickle

host = '127.0.0.1'
port = 8899
buffer_size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

unpickler = pickle.Unpickler(s.makefile("rb"))
print(unpickler.load())
print(unpickler.load())
print(unpickler.load())

CodePudding user response:

Here is a more universal method that also works with non pickled data (eg. receiving data from c socket), you first send in the data len and then the actual data in series to the socket, note that the while loop is there because you are not guaranteed to receive the specify number of bytes in a single call, if the data hasn't arrived yet you will receive less. struct.pack packs data you provided to the function into binary data in the order provided by first argument, 'H' represents unsigned short which is 2 bytes long (max integer you can pack into that is 65535)

Server:

import socket
import pickle, struct

am0=['AQ-20', 'A3000', 'AQ-26', 'A5000', 'AQ-33', 'A5000pro', 'AQ-33pro']
am1=['A10000Pro', 'AQ-43', 'AX-48', 'AX-58', 'AX-68']
am2=['Material', 'nan', 'Steel', 'Stainless S.', 'Stainless S. 1.403']

am00=pickle.dumps(am0)
am00 = struct.pack("H", len(am00))   am00

am01=pickle.dumps(am1)
am01 = struct.pack("H",len(am01))  am01

am02=pickle.dumps(am2)
am02 = struct.pack("H", len(am02))   am02


mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket.bind(('127.0.0.1', 1))
buffer_size = 1024
mysocket.listen()
(client, (ip,port)) = mysocket.accept()
client.send(am00)

#----------------HOW CAN I ADD THEM:----------------
client.send(am01) 
client.send(am02)

mysocket.close()

Client:

import socket
import pickle, struct


host = '127.0.0.1'
port = 1
buffer_size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))


#----------------HOW CAN I RECEIVE THEM SEPERATELY ?---------------
def recv_all(sock:socket.socket):
    data_len = 0
    buffer = b''

    while len(buffer) < 2:
        buffer  = sock.recv(2-len(buffer))
    data_len =  struct.unpack("H", buffer)[0]
            
    buffer = b''
    while len(buffer) < data_len:
        buffer  = sock.recv(data_len-len(buffer))

    return buffer

data1 = pickle.loads(recv_all(s))
print(data1)

data1 = pickle.loads(recv_all(s))
print(data1)

data1 = pickle.loads(recv_all(s))
print(data1)
  • Related