I'm trying to translate the client side of a (POSIX/winsocks) socket-based TCP/IP protocol to native Mac OS X frameworks. Under this protocol, a client port is set up at a specified port, and this socket is then connected to the server at another port. Basically (error checking removed):
InitCommClient( SOCK *clnt, char *address, unsigned short serverPortNr, unsigned short clientPortNr, int timeOutMS )
{
CreateClient( clnt, clientPortNr );
ConnectToServer( *clnt, serverPortNr, address, timeOutMS );
}
CreateClient(SOCK *s, unsigned short port )
{ int yes=1;
*s = socket( AF_INET, SOCK_STREAM, 0 );
setsockopt( *s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes) );
// set up lsock - htons(port), AF_INIT
bind( *s, (SOCKADDR*)&lsock, sizeof(SOCKADDR_IN) );
{ int delay_flag = fcntl(*s, F_GETFL, 0);
delay_flag |= O_NONBLOCK;
fcntl( *s, F_SETFL, delay_flag );
}
}
CreateServer(SOCK *s, unsigned short port )
{ int yes=1;
*s = socket( AF_INET, SOCK_STREAM, 0 );
// set up lsock - htons(port), AF_INIT
bind( *s, (SOCKADDR*)&lsock, sizeof(SOCKADDR_IN) );
listen( *s, 3 );
{ int delay_flag = fcntl(*s, F_GETFL, 0);
delay_flag |= O_NONBLOCK;
fcntl( *s, F_SETFL, delay_flag );
}
}
ConnectToServer(SOCK s, unsigned short port, const char *address, int timeOutms)
{
// set up fsock - inet_addr(address), htons(port), AF_INET
errSock = connect( s, (SOCKADDR*)&fsock, sizeof(SOCKADDR_IN) );
// handle EINPROGRESS, EWOULDBLOCK, EISCONN and ECONNREFUSED, waiting for socket to become writable
}
When I use those functions, I get a working connection with a server running on MS Windows (or under Wine) (though it would appear that I need to handle ECONNREFUSED in a somewhat different way I do under winsocks).
I can also pass the created socket to CFStreamCreatePairWithSocket to obtain a functional NSInputStream, NSOutputStream pair:
InitCommClient( &sServer, ipAddress, ServerPortNr, ClientPortNr, 50 );
CFStreamCreatePairWithSocket( NULL, sServer, (CFReadStreamRef*) &nsReadServer, (CFWriteStreamRef*) &nsWriteServer );
Is it possible to create that pair directly, and if so, how? For now I have only managed to obtain a functional NSInputStream using
CFStreamCreatePairWithSocketToHost( NULL, (CFStringRef) [NSString stringWithUTF8String:ipAddress], ServerPortNr,
(CFReadStreamRef*) &nsReadServer, (CFWriteStreamRef*) &nsWriteServer );
Is it possible that the fine control (client and server port specification, timeout specification, etc) is not available using the high level CFStream/NSStream framework?
I must admit it's a bit (year ...) old, and never was a really high-priority issue for me, and my code hasn't seen any real-world usage yet. This is what I ended up with
NSInputStream *nsReadServer = NULL;
NSOutputStream *nsWriteServer = NULL;
void commsInit(const char *ipAddress)
{
InitCommClient( &sServer, ipAddress, ServerPortNr, ClientPortNr, 50 );
if( sServer != NULLSOCKET ){
CFStreamCreatePairWithSocket( NULL, sServer, (CFReadStreamRef*) &nsReadServer, (CFWriteStreamRef*) &nsWriteServer );
[nsReadServer retain]; [nsWriteServer retain];
[nsReadServer setDelegate:[[OurStreamDelegate alloc] init] ];
[nsReadServer scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[nsReadServer open]; [nsWriteServer open];
}
}
I see the code is a bit of a mess, what with InitCommClient being in a C++ module, but apparently it worked well enough during the testing I did before moving on.
Hope this helps - and feel free to dig through the full code .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.