我正在尝试将(POSIX/winsocks)基于套接字的TCP/IP协议的客户端转换为本机Mac OS X框架。在该协议下,在指定的端口上建立客户端端口,然后将该套接字连接到另一个端口的服务器。基本上(删除错误检查):
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
}
当我使用这些函数时,我与运行在MS Windows(或Wine)上的服务器建立了工作连接(尽管看起来我需要以一种与winsocks不同的方式处理ECONNREFUSED)。
我也可以将创建的套接字传递给CFStreamCreatePairWithSocket,以获得一个功能的NSInputStream, NSOutputStream对:
InitCommClient( &sServer, ipAddress, ServerPortNr, ClientPortNr, 50 );
CFStreamCreatePairWithSocket( NULL, sServer, (CFReadStreamRef*) &nsReadServer, (CFWriteStreamRef*) &nsWriteServer );
是否可以直接创建pair,如果可以,如何创建?现在,我只设法使用
获得一个功能性的NSInputStreamCFStreamCreatePairWithSocketToHost( NULL, (CFStringRef) [NSString stringWithUTF8String:ipAddress], ServerPortNr,
(CFReadStreamRef*) &nsReadServer, (CFWriteStreamRef*) &nsWriteServer );
是否有可能使用高级CFStream/NSStream框架无法使用精细控制(客户端和服务器端口规范,超时规范等)?
我必须承认这已经有一年了,对我来说从来都不是一个真正重要的问题,而且我的代码还没有看到任何实际应用。这就是我最后得到的
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];
}
}
我看到代码有点乱,InitCommClient在c++模块中,但显然它在我继续之前做的测试中工作得很好。
希望这对您有所帮助,您可以随意阅读完整的代码。