0

I have a server:

import socket
import time
import random
from PIL import ImageGrab

server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1',8820))
server_socket.listen(1)

while True:
    print "Waiting for commands"
    a = ImageGrab.grab()
    CommandDict = {"TIME" : time.strftime("%a %b %d %H:%M:%S %Y"),"NAME": "Ori","RANDOM":   str(random.randint(0,10)),"EXIT":"BYE","PRINT SCREEN":a}
    (client_socket, client_address) = server_socket.accept()
    client_data = client_socket.recv(1024)
    print "GOT COMMAND FROM " + client_address[0] + " : " + client_data
    client_socket.send(CommandDict[client_data])
    client_socket.close()

server_socket.close()

and the client:

import socket
from PIL import ImageGrab
while True:
    client_input = raw_input("Enter You Command: ")
    CommandList=["EXIT","TIME","NAME","RANDOM","PRINT SCREEN"]
    if client_input in CommandList:
        my_socket=socket.socket()
        my_socket.connect(('127.0.0.1',8820))
        my_socket.send(client_input)
        data = my_socket.recv(1024) + "\n"
        if client_input=="PRINT SCREEN":
        data.save()
        else:
            print "SERVER: " + data
    else: 
        print "Invalid command. try one of those: " + " , ".join(CommandList) + "\n" + "."


my_socket.close()

When i try this it gives me an error because it trys to send it as a string object. I want to send an object through socket and i want the client to read it. Any ideas?

5
  • What kind of object? Show us the client code. Commented Dec 18, 2014 at 8:50
  • In this server it's an image object but I want to know a way to send all kinds of objects. Commented Dec 18, 2014 at 8:51
  • 1
    You need to serialize the objects before you send them. On the receiving end you restore the objects. Commented Dec 18, 2014 at 8:53
  • Have a look at docs.python.org/2/library/pickle.html#module-pickle Commented Dec 18, 2014 at 9:00
  • 2
    You can send them by serializing them into JSON format. See Making object JSON serializable with regular encoder. Commented Dec 18, 2014 at 9:02

2 Answers 2

2

Python includes an object serialization module called pickle: https://docs.python.org/2/library/pickle.html

You can use pickle.dumps(CommandDict[client_data]) to produce a string which you can then send on a socket. Then use pickle.loads to restore the object on the other side. Of course this requires that the object is "pickleable", but many simple data structures are, or can be made so without much trouble. In your case you may need to add some code to pickle the ImageGrab object type, but try it first and see if it works by default.

Sign up to request clarification or add additional context in comments.

5 Comments

No need to create the string (which will be fairly large as it represents an image in some instances). The following will have better performance: f = my_socket.makefile(); pickle.dump(CommandDict[client_data], f).
It should be pointed out that if pickle is used, the server will have to be able to access the source code for the pickled object(s) in order to reconstitute it or them back into their original form.
@Dunes: thank you for pointing that out, I had thought that should be possible but didn't know offhand exactly how.
I tried to pickle the ImageGrab i and it didnt work, how can i do it? Is there a way to send "unpickleable" objects?
@oridamari You will need to register a function that knows how to pickle and perhaps unpickle the object. See the copy_reg module.
1

The following should allow you to pickle an image. I don't have PIL on my current machine, so I haven't been able to test it properly. The machine

import cPickle as pickle # cPickle is considerably more efficient than pickle
import copy_reg
from StringIO import StringIO
from PIL import Image, ImageGrab

def pickle_image(img):
    """Turns an image into a data stream. Only required on machine sending the 
    image."""
    data = StringIO()
    img.save(data, 'png')
    data.seek(0)
    return unpickle_image, (data,)

def unpickle_image(data):
   """Turns a data stream into an image. Required on both machines"""
    img = Image.open(data)
    data.close() # releases internal buffer immediately
    return img

# tells pickle it should use the function pickle_image to pickle objects of 
# type Image. Required on the machine sending the image
copy_reg.pickle(Image, pickle_image)

some_image = ImageGrab.grab()
# HIGHEST_PROTOCOL uses a more effcient representation of the object
pickled_image = pickle.dumps(some_image, pickle.HIGHEST_PROTOCOL)

unpickled_image = pickle.loads(pickled_image)

In my code I have used dumps and loads to create and use a string representation of the data. Ideally you should be using dump and load, passing my_socket.makefile() as the file argument.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.