Why am I not getting all the bytes of the image in the server?










1














I am building an iOS app that takes a photo and sends it to a TCP server running on my computer. The way I'm doing it is configuring the connection with Streams like this:



func setupCommunication() 
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
"192.168.1.40" as CFString, 2323, &readStream, &writeStream)

outputStream = writeStream!.takeRetainedValue()
outputStream.schedule(in: .current, forMode: .common)
outputStream.open()



Then, when I press the camera button, the photo is taken and sent through the outputStream. Since the TCP server doesn't know how much data it has to read, the first 8 bytes correspond to the size of the image, and the image is sent right after, as we can see in this code:



func photoOutput(_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)

if let image = photo.fileDataRepresentation()
print(image)
print(image.count)

var nBytes = UInt64(image.count)
let nData = Data(bytes: &nBytes, count: 8)
_ = nData.withUnsafeBytes(
outputStream.write($0, maxLength: nData.count)
)

_ = image.withUnsafeBytes(
outputStream.write($0, maxLength: image.count)
)

outputStream.close()




On the server side, which is written in C, I perform the next actions:



Read first 8 bytes to know the size of the image



printf("n[*] New client connectedn");

while (n_recv < sizeof(uint64_t))
if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
printf("n[-] Error reading data from the clientn");
close(client_sd);
close(server_sd);
return 0;


n_recv += n;


memcpy(&img_size, buffer, sizeof(uint64_t));

printf("n[+] Client says he's going to send %llu bytesn", img_size);


Allocate enough memory to store the received image, and if we already read any byte of the image next to the its size, copy it.



if ((img_data = (uint8_t *) malloc(img_size)) == NULL) 
printf("n[-] Error allocating memory for imagen");
close(client_sd);
close(server_sd);
return 0;


n_recv -= sizeof(uint64_t);
if (n_recv > 0)
memcpy(img_data, buffer, n_recv);



From now on, n_recv is the number of bytes received of the image only, not including the first 8 bytes for the size. Then just read till the end.



while (n_recv < img_size) 
if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
printf("n[-] Error reading data from the clientn");
close(client_sd);
close(server_sd);
return 0;


memcpy(img_data + n_recv, buffer, n);
n_recv += n;


printf("n[+] Data correctly recived from clientn");

close(client_sd);
close(server_sd);


This works pretty nice at the beginning. In fact, I can see that I'm getting the right number for the image size every time:



enter image description here



However, I'm not getting the full image, and the server just keeps waiting blocked in the read function. To see what's happening, I added this



printf("%llun", n_recv);


inside the loop for reading the image, to watch the number of bytes received. It stops in the middle of the image, for some reason I'm not able to explain:



enter image description here



What's the problem that is causing the communication to stop? Is the problem in the server code or is it something related to iOS app?










share|improve this question


























    1














    I am building an iOS app that takes a photo and sends it to a TCP server running on my computer. The way I'm doing it is configuring the connection with Streams like this:



    func setupCommunication() 
    var readStream: Unmanaged<CFReadStream>?
    var writeStream: Unmanaged<CFWriteStream>?

    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
    "192.168.1.40" as CFString, 2323, &readStream, &writeStream)

    outputStream = writeStream!.takeRetainedValue()
    outputStream.schedule(in: .current, forMode: .common)
    outputStream.open()



    Then, when I press the camera button, the photo is taken and sent through the outputStream. Since the TCP server doesn't know how much data it has to read, the first 8 bytes correspond to the size of the image, and the image is sent right after, as we can see in this code:



    func photoOutput(_ output: AVCapturePhotoOutput,
    didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)

    if let image = photo.fileDataRepresentation()
    print(image)
    print(image.count)

    var nBytes = UInt64(image.count)
    let nData = Data(bytes: &nBytes, count: 8)
    _ = nData.withUnsafeBytes(
    outputStream.write($0, maxLength: nData.count)
    )

    _ = image.withUnsafeBytes(
    outputStream.write($0, maxLength: image.count)
    )

    outputStream.close()




    On the server side, which is written in C, I perform the next actions:



    Read first 8 bytes to know the size of the image



    printf("n[*] New client connectedn");

    while (n_recv < sizeof(uint64_t))
    if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
    printf("n[-] Error reading data from the clientn");
    close(client_sd);
    close(server_sd);
    return 0;


    n_recv += n;


    memcpy(&img_size, buffer, sizeof(uint64_t));

    printf("n[+] Client says he's going to send %llu bytesn", img_size);


    Allocate enough memory to store the received image, and if we already read any byte of the image next to the its size, copy it.



    if ((img_data = (uint8_t *) malloc(img_size)) == NULL) 
    printf("n[-] Error allocating memory for imagen");
    close(client_sd);
    close(server_sd);
    return 0;


    n_recv -= sizeof(uint64_t);
    if (n_recv > 0)
    memcpy(img_data, buffer, n_recv);



    From now on, n_recv is the number of bytes received of the image only, not including the first 8 bytes for the size. Then just read till the end.



    while (n_recv < img_size) 
    if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
    printf("n[-] Error reading data from the clientn");
    close(client_sd);
    close(server_sd);
    return 0;


    memcpy(img_data + n_recv, buffer, n);
    n_recv += n;


    printf("n[+] Data correctly recived from clientn");

    close(client_sd);
    close(server_sd);


    This works pretty nice at the beginning. In fact, I can see that I'm getting the right number for the image size every time:



    enter image description here



    However, I'm not getting the full image, and the server just keeps waiting blocked in the read function. To see what's happening, I added this



    printf("%llun", n_recv);


    inside the loop for reading the image, to watch the number of bytes received. It stops in the middle of the image, for some reason I'm not able to explain:



    enter image description here



    What's the problem that is causing the communication to stop? Is the problem in the server code or is it something related to iOS app?










    share|improve this question
























      1












      1








      1







      I am building an iOS app that takes a photo and sends it to a TCP server running on my computer. The way I'm doing it is configuring the connection with Streams like this:



      func setupCommunication() 
      var readStream: Unmanaged<CFReadStream>?
      var writeStream: Unmanaged<CFWriteStream>?

      CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
      "192.168.1.40" as CFString, 2323, &readStream, &writeStream)

      outputStream = writeStream!.takeRetainedValue()
      outputStream.schedule(in: .current, forMode: .common)
      outputStream.open()



      Then, when I press the camera button, the photo is taken and sent through the outputStream. Since the TCP server doesn't know how much data it has to read, the first 8 bytes correspond to the size of the image, and the image is sent right after, as we can see in this code:



      func photoOutput(_ output: AVCapturePhotoOutput,
      didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)

      if let image = photo.fileDataRepresentation()
      print(image)
      print(image.count)

      var nBytes = UInt64(image.count)
      let nData = Data(bytes: &nBytes, count: 8)
      _ = nData.withUnsafeBytes(
      outputStream.write($0, maxLength: nData.count)
      )

      _ = image.withUnsafeBytes(
      outputStream.write($0, maxLength: image.count)
      )

      outputStream.close()




      On the server side, which is written in C, I perform the next actions:



      Read first 8 bytes to know the size of the image



      printf("n[*] New client connectedn");

      while (n_recv < sizeof(uint64_t))
      if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
      printf("n[-] Error reading data from the clientn");
      close(client_sd);
      close(server_sd);
      return 0;


      n_recv += n;


      memcpy(&img_size, buffer, sizeof(uint64_t));

      printf("n[+] Client says he's going to send %llu bytesn", img_size);


      Allocate enough memory to store the received image, and if we already read any byte of the image next to the its size, copy it.



      if ((img_data = (uint8_t *) malloc(img_size)) == NULL) 
      printf("n[-] Error allocating memory for imagen");
      close(client_sd);
      close(server_sd);
      return 0;


      n_recv -= sizeof(uint64_t);
      if (n_recv > 0)
      memcpy(img_data, buffer, n_recv);



      From now on, n_recv is the number of bytes received of the image only, not including the first 8 bytes for the size. Then just read till the end.



      while (n_recv < img_size) 
      if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
      printf("n[-] Error reading data from the clientn");
      close(client_sd);
      close(server_sd);
      return 0;


      memcpy(img_data + n_recv, buffer, n);
      n_recv += n;


      printf("n[+] Data correctly recived from clientn");

      close(client_sd);
      close(server_sd);


      This works pretty nice at the beginning. In fact, I can see that I'm getting the right number for the image size every time:



      enter image description here



      However, I'm not getting the full image, and the server just keeps waiting blocked in the read function. To see what's happening, I added this



      printf("%llun", n_recv);


      inside the loop for reading the image, to watch the number of bytes received. It stops in the middle of the image, for some reason I'm not able to explain:



      enter image description here



      What's the problem that is causing the communication to stop? Is the problem in the server code or is it something related to iOS app?










      share|improve this question













      I am building an iOS app that takes a photo and sends it to a TCP server running on my computer. The way I'm doing it is configuring the connection with Streams like this:



      func setupCommunication() 
      var readStream: Unmanaged<CFReadStream>?
      var writeStream: Unmanaged<CFWriteStream>?

      CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
      "192.168.1.40" as CFString, 2323, &readStream, &writeStream)

      outputStream = writeStream!.takeRetainedValue()
      outputStream.schedule(in: .current, forMode: .common)
      outputStream.open()



      Then, when I press the camera button, the photo is taken and sent through the outputStream. Since the TCP server doesn't know how much data it has to read, the first 8 bytes correspond to the size of the image, and the image is sent right after, as we can see in this code:



      func photoOutput(_ output: AVCapturePhotoOutput,
      didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)

      if let image = photo.fileDataRepresentation()
      print(image)
      print(image.count)

      var nBytes = UInt64(image.count)
      let nData = Data(bytes: &nBytes, count: 8)
      _ = nData.withUnsafeBytes(
      outputStream.write($0, maxLength: nData.count)
      )

      _ = image.withUnsafeBytes(
      outputStream.write($0, maxLength: image.count)
      )

      outputStream.close()




      On the server side, which is written in C, I perform the next actions:



      Read first 8 bytes to know the size of the image



      printf("n[*] New client connectedn");

      while (n_recv < sizeof(uint64_t))
      if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
      printf("n[-] Error reading data from the clientn");
      close(client_sd);
      close(server_sd);
      return 0;


      n_recv += n;


      memcpy(&img_size, buffer, sizeof(uint64_t));

      printf("n[+] Client says he's going to send %llu bytesn", img_size);


      Allocate enough memory to store the received image, and if we already read any byte of the image next to the its size, copy it.



      if ((img_data = (uint8_t *) malloc(img_size)) == NULL) 
      printf("n[-] Error allocating memory for imagen");
      close(client_sd);
      close(server_sd);
      return 0;


      n_recv -= sizeof(uint64_t);
      if (n_recv > 0)
      memcpy(img_data, buffer, n_recv);



      From now on, n_recv is the number of bytes received of the image only, not including the first 8 bytes for the size. Then just read till the end.



      while (n_recv < img_size) 
      if ((n = read(client_sd, buffer, BUF_SIZ)) == -1)
      printf("n[-] Error reading data from the clientn");
      close(client_sd);
      close(server_sd);
      return 0;


      memcpy(img_data + n_recv, buffer, n);
      n_recv += n;


      printf("n[+] Data correctly recived from clientn");

      close(client_sd);
      close(server_sd);


      This works pretty nice at the beginning. In fact, I can see that I'm getting the right number for the image size every time:



      enter image description here



      However, I'm not getting the full image, and the server just keeps waiting blocked in the read function. To see what's happening, I added this



      printf("%llun", n_recv);


      inside the loop for reading the image, to watch the number of bytes received. It stops in the middle of the image, for some reason I'm not able to explain:



      enter image description here



      What's the problem that is causing the communication to stop? Is the problem in the server code or is it something related to iOS app?







      ios c tcp server stream






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 12 '18 at 22:17









      Jaime_mc2

      16411




      16411






















          1 Answer
          1






          active

          oldest

          votes


















          1














          First, the C code looks okay to me.. but you realize you are missing return code/result handling in Swift?



          In the C code you are checking the return value of recv to know if the bytes were read.. IE: You are checking if read returns -1..



          However, in the swift code you make the assumption that ALL the data was written.. You never checked the result of the write operation on OutputStream which tells you how many bytes were written or returns -1 on failure..



          You should be doing the same thing (after all, you did it in C).. For such cases I created two extensions:



          extension InputStream 
          /**
          * Reads from the stream into a data buffer.
          * Returns the count of the amount of bytes read from the stream.
          * Returns -1 if reading fails or an error has occurred on the stream.
          **/
          func read(data: inout Data) -> Int
          let bufferSize = 1024
          var totalBytesRead = 0

          while true
          let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
          let count = read(buffer, maxLength: bufferSize)
          if count == 0
          return totalBytesRead


          if count == -1
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          data.append(buffer, count: count)
          totalBytesRead += count

          return totalBytesRead



          extension OutputStream
          /**
          * Writes from a buffer into the stream.
          * Returns the count of the amount of bytes written to the stream.
          * Returns -1 if writing fails or an error has occurred on the stream.
          **/
          func write(data: Data) -> Int
          var bytesRemaining = data.count
          var bytesWritten = 0

          while bytesRemaining > 0
          let count = data.withUnsafeBytes
          self.write($0.advanced(by: bytesWritten), maxLength: bytesRemaining)


          if count == 0
          return bytesWritten


          if count < 0
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          bytesRemaining -= count
          bytesWritten += count


          return bytesWritten




          Usage:



          var readStream: Unmanaged<CFReadStream>?
          var writeStream: Unmanaged<CFWriteStream>?

          //For testing I used 127.0.0.1
          CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, "192.168.1.40" as CFString, 2323, &readStream, &writeStream)


          //Actually not sure if these need to be retained or unretained might be fine..
          //Again, not sure..
          var inputStream = readStream!.takeRetainedValue() as InputStream
          var outputStream = writeStream!.takeRetainedValue() as OutputStream

          inputStream.schedule(in: .current, forMode: .common)
          outputStream.schedule(in: .current, forMode: .common)

          inputStream.open()
          outputStream.open()


          var dataToWrite = Data() //Your Image
          var dataRead = Data(capacity: 256) //Server response -- Pre-Allocate something large enough that you "think" you might read..

          outputStream.write(data: dataToWrite)
          inputStream.read(data: &dataRead)


          Now you get error handling (printing) and you have buffered reading/writing.. After all, you're not guaranteed that the socket or pipe or w/e.. the stream is attached to has read/written ALL your bytes at once.. hence the reading/writing chunks.






          share|improve this answer






















          • Thank you! It worked nice :) By the way, do you know how can I learn more about networking with iOS and Swift?
            – Jaime_mc2
            Nov 13 '18 at 8:54










          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270893%2fwhy-am-i-not-getting-all-the-bytes-of-the-image-in-the-server%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          First, the C code looks okay to me.. but you realize you are missing return code/result handling in Swift?



          In the C code you are checking the return value of recv to know if the bytes were read.. IE: You are checking if read returns -1..



          However, in the swift code you make the assumption that ALL the data was written.. You never checked the result of the write operation on OutputStream which tells you how many bytes were written or returns -1 on failure..



          You should be doing the same thing (after all, you did it in C).. For such cases I created two extensions:



          extension InputStream 
          /**
          * Reads from the stream into a data buffer.
          * Returns the count of the amount of bytes read from the stream.
          * Returns -1 if reading fails or an error has occurred on the stream.
          **/
          func read(data: inout Data) -> Int
          let bufferSize = 1024
          var totalBytesRead = 0

          while true
          let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
          let count = read(buffer, maxLength: bufferSize)
          if count == 0
          return totalBytesRead


          if count == -1
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          data.append(buffer, count: count)
          totalBytesRead += count

          return totalBytesRead



          extension OutputStream
          /**
          * Writes from a buffer into the stream.
          * Returns the count of the amount of bytes written to the stream.
          * Returns -1 if writing fails or an error has occurred on the stream.
          **/
          func write(data: Data) -> Int
          var bytesRemaining = data.count
          var bytesWritten = 0

          while bytesRemaining > 0
          let count = data.withUnsafeBytes
          self.write($0.advanced(by: bytesWritten), maxLength: bytesRemaining)


          if count == 0
          return bytesWritten


          if count < 0
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          bytesRemaining -= count
          bytesWritten += count


          return bytesWritten




          Usage:



          var readStream: Unmanaged<CFReadStream>?
          var writeStream: Unmanaged<CFWriteStream>?

          //For testing I used 127.0.0.1
          CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, "192.168.1.40" as CFString, 2323, &readStream, &writeStream)


          //Actually not sure if these need to be retained or unretained might be fine..
          //Again, not sure..
          var inputStream = readStream!.takeRetainedValue() as InputStream
          var outputStream = writeStream!.takeRetainedValue() as OutputStream

          inputStream.schedule(in: .current, forMode: .common)
          outputStream.schedule(in: .current, forMode: .common)

          inputStream.open()
          outputStream.open()


          var dataToWrite = Data() //Your Image
          var dataRead = Data(capacity: 256) //Server response -- Pre-Allocate something large enough that you "think" you might read..

          outputStream.write(data: dataToWrite)
          inputStream.read(data: &dataRead)


          Now you get error handling (printing) and you have buffered reading/writing.. After all, you're not guaranteed that the socket or pipe or w/e.. the stream is attached to has read/written ALL your bytes at once.. hence the reading/writing chunks.






          share|improve this answer






















          • Thank you! It worked nice :) By the way, do you know how can I learn more about networking with iOS and Swift?
            – Jaime_mc2
            Nov 13 '18 at 8:54















          1














          First, the C code looks okay to me.. but you realize you are missing return code/result handling in Swift?



          In the C code you are checking the return value of recv to know if the bytes were read.. IE: You are checking if read returns -1..



          However, in the swift code you make the assumption that ALL the data was written.. You never checked the result of the write operation on OutputStream which tells you how many bytes were written or returns -1 on failure..



          You should be doing the same thing (after all, you did it in C).. For such cases I created two extensions:



          extension InputStream 
          /**
          * Reads from the stream into a data buffer.
          * Returns the count of the amount of bytes read from the stream.
          * Returns -1 if reading fails or an error has occurred on the stream.
          **/
          func read(data: inout Data) -> Int
          let bufferSize = 1024
          var totalBytesRead = 0

          while true
          let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
          let count = read(buffer, maxLength: bufferSize)
          if count == 0
          return totalBytesRead


          if count == -1
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          data.append(buffer, count: count)
          totalBytesRead += count

          return totalBytesRead



          extension OutputStream
          /**
          * Writes from a buffer into the stream.
          * Returns the count of the amount of bytes written to the stream.
          * Returns -1 if writing fails or an error has occurred on the stream.
          **/
          func write(data: Data) -> Int
          var bytesRemaining = data.count
          var bytesWritten = 0

          while bytesRemaining > 0
          let count = data.withUnsafeBytes
          self.write($0.advanced(by: bytesWritten), maxLength: bytesRemaining)


          if count == 0
          return bytesWritten


          if count < 0
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          bytesRemaining -= count
          bytesWritten += count


          return bytesWritten




          Usage:



          var readStream: Unmanaged<CFReadStream>?
          var writeStream: Unmanaged<CFWriteStream>?

          //For testing I used 127.0.0.1
          CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, "192.168.1.40" as CFString, 2323, &readStream, &writeStream)


          //Actually not sure if these need to be retained or unretained might be fine..
          //Again, not sure..
          var inputStream = readStream!.takeRetainedValue() as InputStream
          var outputStream = writeStream!.takeRetainedValue() as OutputStream

          inputStream.schedule(in: .current, forMode: .common)
          outputStream.schedule(in: .current, forMode: .common)

          inputStream.open()
          outputStream.open()


          var dataToWrite = Data() //Your Image
          var dataRead = Data(capacity: 256) //Server response -- Pre-Allocate something large enough that you "think" you might read..

          outputStream.write(data: dataToWrite)
          inputStream.read(data: &dataRead)


          Now you get error handling (printing) and you have buffered reading/writing.. After all, you're not guaranteed that the socket or pipe or w/e.. the stream is attached to has read/written ALL your bytes at once.. hence the reading/writing chunks.






          share|improve this answer






















          • Thank you! It worked nice :) By the way, do you know how can I learn more about networking with iOS and Swift?
            – Jaime_mc2
            Nov 13 '18 at 8:54













          1












          1








          1






          First, the C code looks okay to me.. but you realize you are missing return code/result handling in Swift?



          In the C code you are checking the return value of recv to know if the bytes were read.. IE: You are checking if read returns -1..



          However, in the swift code you make the assumption that ALL the data was written.. You never checked the result of the write operation on OutputStream which tells you how many bytes were written or returns -1 on failure..



          You should be doing the same thing (after all, you did it in C).. For such cases I created two extensions:



          extension InputStream 
          /**
          * Reads from the stream into a data buffer.
          * Returns the count of the amount of bytes read from the stream.
          * Returns -1 if reading fails or an error has occurred on the stream.
          **/
          func read(data: inout Data) -> Int
          let bufferSize = 1024
          var totalBytesRead = 0

          while true
          let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
          let count = read(buffer, maxLength: bufferSize)
          if count == 0
          return totalBytesRead


          if count == -1
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          data.append(buffer, count: count)
          totalBytesRead += count

          return totalBytesRead



          extension OutputStream
          /**
          * Writes from a buffer into the stream.
          * Returns the count of the amount of bytes written to the stream.
          * Returns -1 if writing fails or an error has occurred on the stream.
          **/
          func write(data: Data) -> Int
          var bytesRemaining = data.count
          var bytesWritten = 0

          while bytesRemaining > 0
          let count = data.withUnsafeBytes
          self.write($0.advanced(by: bytesWritten), maxLength: bytesRemaining)


          if count == 0
          return bytesWritten


          if count < 0
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          bytesRemaining -= count
          bytesWritten += count


          return bytesWritten




          Usage:



          var readStream: Unmanaged<CFReadStream>?
          var writeStream: Unmanaged<CFWriteStream>?

          //For testing I used 127.0.0.1
          CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, "192.168.1.40" as CFString, 2323, &readStream, &writeStream)


          //Actually not sure if these need to be retained or unretained might be fine..
          //Again, not sure..
          var inputStream = readStream!.takeRetainedValue() as InputStream
          var outputStream = writeStream!.takeRetainedValue() as OutputStream

          inputStream.schedule(in: .current, forMode: .common)
          outputStream.schedule(in: .current, forMode: .common)

          inputStream.open()
          outputStream.open()


          var dataToWrite = Data() //Your Image
          var dataRead = Data(capacity: 256) //Server response -- Pre-Allocate something large enough that you "think" you might read..

          outputStream.write(data: dataToWrite)
          inputStream.read(data: &dataRead)


          Now you get error handling (printing) and you have buffered reading/writing.. After all, you're not guaranteed that the socket or pipe or w/e.. the stream is attached to has read/written ALL your bytes at once.. hence the reading/writing chunks.






          share|improve this answer














          First, the C code looks okay to me.. but you realize you are missing return code/result handling in Swift?



          In the C code you are checking the return value of recv to know if the bytes were read.. IE: You are checking if read returns -1..



          However, in the swift code you make the assumption that ALL the data was written.. You never checked the result of the write operation on OutputStream which tells you how many bytes were written or returns -1 on failure..



          You should be doing the same thing (after all, you did it in C).. For such cases I created two extensions:



          extension InputStream 
          /**
          * Reads from the stream into a data buffer.
          * Returns the count of the amount of bytes read from the stream.
          * Returns -1 if reading fails or an error has occurred on the stream.
          **/
          func read(data: inout Data) -> Int
          let bufferSize = 1024
          var totalBytesRead = 0

          while true
          let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
          let count = read(buffer, maxLength: bufferSize)
          if count == 0
          return totalBytesRead


          if count == -1
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          data.append(buffer, count: count)
          totalBytesRead += count

          return totalBytesRead



          extension OutputStream
          /**
          * Writes from a buffer into the stream.
          * Returns the count of the amount of bytes written to the stream.
          * Returns -1 if writing fails or an error has occurred on the stream.
          **/
          func write(data: Data) -> Int
          var bytesRemaining = data.count
          var bytesWritten = 0

          while bytesRemaining > 0
          let count = data.withUnsafeBytes
          self.write($0.advanced(by: bytesWritten), maxLength: bytesRemaining)


          if count == 0
          return bytesWritten


          if count < 0
          if let streamError = self.streamError
          debugPrint("Stream Error: (String(describing: streamError))")

          return -1


          bytesRemaining -= count
          bytesWritten += count


          return bytesWritten




          Usage:



          var readStream: Unmanaged<CFReadStream>?
          var writeStream: Unmanaged<CFWriteStream>?

          //For testing I used 127.0.0.1
          CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, "192.168.1.40" as CFString, 2323, &readStream, &writeStream)


          //Actually not sure if these need to be retained or unretained might be fine..
          //Again, not sure..
          var inputStream = readStream!.takeRetainedValue() as InputStream
          var outputStream = writeStream!.takeRetainedValue() as OutputStream

          inputStream.schedule(in: .current, forMode: .common)
          outputStream.schedule(in: .current, forMode: .common)

          inputStream.open()
          outputStream.open()


          var dataToWrite = Data() //Your Image
          var dataRead = Data(capacity: 256) //Server response -- Pre-Allocate something large enough that you "think" you might read..

          outputStream.write(data: dataToWrite)
          inputStream.read(data: &dataRead)


          Now you get error handling (printing) and you have buffered reading/writing.. After all, you're not guaranteed that the socket or pipe or w/e.. the stream is attached to has read/written ALL your bytes at once.. hence the reading/writing chunks.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 13 '18 at 1:27

























          answered Nov 13 '18 at 1:22









          Brandon

          13.1k749121




          13.1k749121











          • Thank you! It worked nice :) By the way, do you know how can I learn more about networking with iOS and Swift?
            – Jaime_mc2
            Nov 13 '18 at 8:54
















          • Thank you! It worked nice :) By the way, do you know how can I learn more about networking with iOS and Swift?
            – Jaime_mc2
            Nov 13 '18 at 8:54















          Thank you! It worked nice :) By the way, do you know how can I learn more about networking with iOS and Swift?
          – Jaime_mc2
          Nov 13 '18 at 8:54




          Thank you! It worked nice :) By the way, do you know how can I learn more about networking with iOS and Swift?
          – Jaime_mc2
          Nov 13 '18 at 8:54

















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270893%2fwhy-am-i-not-getting-all-the-bytes-of-the-image-in-the-server%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          27

          Top Tejano songwriter Luis Silva dead of heart attack at 64

          Category:Rhetoric