3

I really would like to use the getBuffer:length: method of an NSInputStream. After a lot of research i couldn't find a valid example that uses this method, because most people really needed read: maxLength:.

So now some facts on the surroundings: * I'm developing an app for the iPhone, iOS 3.1.3 * I've established a network communication via sockets * That network connection actually works; so i didn't forget to add a a stream to the runloop or a valid delegate or such things - it already works * I'm only sending and receiving Strings over the network. * I've set a valid delegate that implements stream: handleEvent: correctly (differentiates between the received events and takes proper actions). I'm not sure if the receiving code is 100% correct as i sometimes receive a message twice. This could also be caused be a faulty implementation on the device i'm communicating with. To figure out which of the last to points it is, i'm trying to find out how many bytes are really on the receiving buffer when i receive a "NSStreamEventHasBytesAvailable" event. As i don't know for sure that my implementation is correct, but i wanted to know the actual number of bytes i received, i wanted to use getBuffer: length: and take a look at the length afterwards. Strange thing is: the length is never printed on the console, as [((NSInputStream *) stream) getBuffer: &buf length: &numBytes] always evaluates to FALSE. Anyway, the part of code afterwards works correctly, receives the message in the buffer and forwards it correctly - works good. Question remains: Why doesn't getBuffer: length: work? The code of interest is here:

` case NSStreamEventHasBytesAvailable: {

        uint8_t *buf;
        unsigned int numBytes;

        if ([((NSInputStream *) stream) getBuffer: &buf length: &numBytes]) {
            NSLog(@"\t\tBytes in the buffer: %i", &numBytes);
        }

        uint8_t buffer[BUFFER_SIZE];
        int len = [((NSInputStream *) stream) read: buffer 
                                         maxLength: BUFFER_SIZE];
        NSLog(@"\tread: %i bytes", len);

        /*
         if len > 0: len is equal to the filled byte elements
         if len == 0: end of buffer was reached while reading
         if len < 0: something terrible happened...
         */
        if (len > 0) {
            /* 1. create string from received byte buffer */
            NSString *msg = [[NSString alloc] initWithBytes: buffer length: len encoding: NSASCIIStringEncoding];
            NSLog(@"\tcontained message: %@", msg);
            /* 2. inform communicator about received message */
            [communicator received: msg];
            [msg release];
        }

        if (len < 0) {
            [communicator received: @"Error!"];
        }
        break;
    }

`

Would be nice if someone could help me!

m Jae
  • 725
  • 2
  • 8
  • 20

3 Answers3

10

Darwin is open source, so "the truth is out there". The source for NSStream shows that GSInetInputStream is the class that implements a NSInputStream for a socket, and the implementation of getBuffer:length: for that class answers the question succinctly:

- (BOOL) getBuffer: (uint8_t **)buffer length: (unsigned int *)len
{
  return NO;
}

Found here.

stevex
  • 5,589
  • 37
  • 52
  • Hi, can you check my [question about getBuffer in Swift](http://stackoverflow.com/questions/40045665/size-of-the-nsinputstream-buffer)? I have a very strange issue, proposed answers from advanced users not works. Regards! – konstantin_doncov Oct 16 '16 at 01:29
0

I think that getBuffer isn't working because there isn't a buffer yet, you are reading into the buffer afterwards, so it cant get the pointer to the buffer yet...

Oliver
  • 566
  • 4
  • 10
  • doesn't make sense, as that code only gets executed when i receive a "NSStreamEventHasBytesAvailable" event, so there is data available in the underlying buffer (which i want to get a reference to by calling `getBuffer:length:`. i just moved the `if getBuffer:length:` block below the `read:maxLength:` block, and as expected: nothing changed – m Jae Nov 02 '10 at 07:34
  • furthermore: i'm trying to READ FROM that buffer not WRITING into it (i think that is what you meant by "reading into the buffer" ?). – m Jae Nov 02 '10 at 12:16
  • the event that bytes are available does not mean they are in the buffer yet, there are bytes ready to be read into a buffer from the stream. pretend that you are opening a stream to a file, when you open the stream, there are bytes available over the stream to be read, but none of the file has been read into the buffer yet. By "reading into the buffer" I meant getting bytes over the stream and putting them into a buffer. – Oliver Nov 03 '10 at 06:24
0

ah, i think i get what you mean. but i suppose the following code should then evaluate to TRUE at least after reading into the buffer? i'm just asking, because it doesn't, getBuffer:length: still seems not to work. the communication using the available bytes works well, but the question remains...

        uint8_t *buf1;
        unsigned int numBytes1;
        if ([((NSInputStream *) stream) getBuffer: &buf length: &numBytes]) {
            NSLog(@"\t\tBytes are in the buffer before Op.");
        }

        uint8_t buffer[BUFFER_SIZE];
        int len = [((NSInputStream *) stream) read: buffer 
                                         maxLength: BUFFER_SIZE];

        uint8_t *buf2;
        unsigned int numBytes2;
        if ([((NSInputStream *) stream) getBuffer: &buf2 length: &numBytes2]) {
            NSLog(@"\t\tBytes in the buffer after Op.");
        }

sorry for creating an answer to my own question; but the comment was able to handle so much code...

m Jae
  • 725
  • 2
  • 8
  • 20
  • What happens if you change numbytes to be NSUInteger instead of "unsigned int"? – Oliver Nov 17 '10 at 11:49
  • the buffer is not available, neither before nor after the read: maxLength: . doesn't matter to me atm as i debugged that part of my app without the getBuffer: length: . thanks ayway for your time, Oliver! – m Jae Nov 23 '10 at 06:43