[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Q] NSFileHandle -readDataOfLength behaviour
From: |
Vaisburd, Haim |
Subject: |
[Q] NSFileHandle -readDataOfLength behaviour |
Date: |
Thu, 12 Apr 2007 18:21:41 -0700 |
Hi,
While working on my byte stream functions and trying to base them on
NSFileHandle instead of NSStreams I discovered a strange feature of
[NSFileHandle -readDataOfLength:] implementation in GNUstep.
I was trying to determine whether this method blocks until it reads
the requested number of bytes or it blocks only until anything is
available,
then it returns what's avaiable up to the length (i.e. normal read()
semantics).
Apparently, the code does both!
It depends on the length: if the length is greater that 65536, the
method
tries to read chunks in the blocking mode and does not stop until
it gets the full length, which can very well block.
If the length is less ot equal than 65536, the code issues read() or
recv()
just once.
It looks to me like a bug: changing the length parameter may drastically
modify the program behavior.
The only idea I have in mind how it would be fixed is to use
non-blocking
mode for read() and call read() in a loop until it returns EAGAIN.
On the other hand I do not know where the restriction for 65536 came
from.
I wrote a test program, here is the client that writes a request to the
local socket and receives the response. The test requires the server
that
just echoes back what it got.
It's easy for me to attach the client since it is short, my server is
bigger
and messier that's needed to test this case, however, this all seems
like an
overkill because mere examination of the -readDataOfLength: ought to do.
Thank you,
Tima
----------------------- begin ------------------------
#include <Foundation/Foundation.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
//#define TEST_LENGTH 65536
#define TEST_LENGTH 65537
void fatal( const char * s )
{
char buf[40];
sprintf( buf, "%s", s );
perror( buf );
exit(1);
}
int connectToSocket( const char * path )
{
int socket_fd = socket( PF_UNIX, SOCK_STREAM, 0 );
if ( socket_fd == -1 )
fatal( "socket" );
struct sockaddr_un sa;
memset( &sa, 0, sizeof(sa) );
sa.sun_family = AF_UNIX; // unix domain socket
strncpy( sa.sun_path, path, sizeof(sa.sun_path)-1 );
if ( connect( socket_fd, (struct sockaddr *)&sa, sizeof( sa ) ) == -1
)
fatal( "connect" );
return socket_fd;
}
int main(int argc, char ** argv )
{
[NSAutoreleasePool new];
const char * path = "/tmp/agajd";
NSLog( @"Connecting to local socket %s", path );
int fd = connectToSocket( path );
NSFileHandle * fh = [[NSFileHandle alloc] initWithFileDescriptor:
fd];
const char * request = "{1,2,3}";
[fh writeData: [NSData dataWithBytes: request length:
strlen(request)]];
NSData * resp = [fh readDataOfLength: TEST_LENGTH];
NSString * response = [[NSString alloc] initWithData: resp
encoding:
NSASCIIStringEncoding];
NSLog( @"got response: \"%@\"", response );
return 0;
}
---------------------- end ----------------------------
- [Q] NSFileHandle -readDataOfLength behaviour,
Vaisburd, Haim <=