I created a socket server. how do I know the connection is closed by the client?

Hi experts.

I created a socket server and when the server accept a connection, I associate the CFSocketNativeHandle with NSInputStream and NSOutputStream.

I implement method - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode.


I think the connection is closed by the client, if I received event NSStreamEventHasBytesAvailable and the length of data i read is 0.

like the following codes:

is it right ? if not, how do I know the connection is closed by the client?

thanks.


- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode)
    {
        case NSStreamEventOpenCompleted:
            break;
            
        case NSStreamEventHasBytesAvailable:
        {
            NSMutableData *data = [NSMutableData data];
            uint8_t buffer[1024];
            NSInputStream *inputStream = (NSInputStream *)aStream;
            while (inputStream.hasBytesAvailable)
            {
                NSInteger readSize = [inputStream read:buffer maxLength:kBufferSize];
                if (readSize > 0)
                {
                    [data appendBytes:buffer length:readSize];
                } else if (-1 == readSize)
                {
                    NSError *error = aStream.streamError;
                    if (error)
                    {
                        // ...
                    }
                }
            }
            
            if(0 == data.length)
            {// the connection is closed by the client
            }
        }
            break;

            // ...
            
        default:
            break;
    }
}

Accepted Reply

Having your

NSStreamEventHasBytesAvailable
handler loop while
hasBytesAvailable
returns true is not best practice. You should instead have it call
-read:maxLength:
once, process the results, and then return.

In terms of how to detect EOF, there are two approaches you can use. The first approach is to check the result from

-read:maxLength:
as follows:
  • If it’s positive, you have some bytes to process.

  • If it’s negative, you have an error. Use the

    streamError
    property to get the details.
  • If it’s 0, it’s an EOF.

In the second approach, you call

-read:maxLength:
and just return in the non-positive cases. You’ll then receive an
NSStreamEventErrorOccurred
event if there was an error or an
NSStreamEventEndEncountered
event if there was an EOF.

I used to use the first approach but I now use the second approach because I’ve found that it makes my code easier.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

Having your

NSStreamEventHasBytesAvailable
handler loop while
hasBytesAvailable
returns true is not best practice. You should instead have it call
-read:maxLength:
once, process the results, and then return.

In terms of how to detect EOF, there are two approaches you can use. The first approach is to check the result from

-read:maxLength:
as follows:
  • If it’s positive, you have some bytes to process.

  • If it’s negative, you have an error. Use the

    streamError
    property to get the details.
  • If it’s 0, it’s an EOF.

In the second approach, you call

-read:maxLength:
and just return in the non-positive cases. You’ll then receive an
NSStreamEventErrorOccurred
event if there was an error or an
NSStreamEventEndEncountered
event if there was an EOF.

I used to use the first approach but I now use the second approach because I’ve found that it makes my code easier.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"