tcpjpegtwistednsdatansoutputstream

Sending JPEG NSData over TCP to Python server


I have a Python tcp server that has a iOS client. It is able to send data and receive, the only issue I am having is likely with encoding. I am trying to send a JPEG through TCP to the Python server and write the data to a JPEG on the server. The jpeg keeps corrupting.

Client Obj-C code:

[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection
                                                           completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

            NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
            UIImage *image = [[UIImage alloc] initWithData:imageData];
                                                               iv = [[UIImageView alloc] initWithImage:image];


                                                               [iv setFrame:[[self view]frame]];





                                                               ConnectionManager *netCon = [ConnectionManager alloc];
                                                               conMan = netCon;
                                                               [conMan initNetworkCommunication];



                                                               [conMan.outputStream write:(const uint8_t *)[imageData bytes] maxLength:[imageData length]];



        }];

And here is the python (twisted) server code:

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor

class IphoneChat(Protocol):
    def connectionMade(self):
        self.factory.clients.append(self)
        print "clients are ", self.factory.clients

    def connectionLost(self, reason):
        self.factory.clients.remove(self)

    def dataReceived(self, data):
        file = open('test.jpeg','w')

        file.write(data)
        file.close()


factory = Factory()

factory.clients=[]


factory.protocol = IphoneChat
reactor.listenTCP(2000, factory)
print "Iphone Chat server started"
reactor.run()

Solution

  • TCP is a stream-oriented protocol. It doesn't have messages (therefore it doesn't have stable message boundaries). dataReceived is called with some bytes - at least one, but how many more than that you can't really know.

    You can't just treat whatever is passed to dataReceived as the complete image data. It is some bytes from the image data. Chances are dataReceived will be called repeatedly, each time with some more bytes from the image data. You have to re-assemble the data passed to these multiple calls into the complete image data.