简体   繁体   English

MacOSX:使用特定的客户端和服务器端口创建CFStream / NSStream

[英]MacOSX: creating a CFStream/NSStream with specific client and server ports

I'm trying to translate the client side of a (POSIX/winsocks) socket-based TCP/IP protocol to native Mac OS X frameworks. 我正在尝试将(POSIX / winsocks)基于套接字的TCP / IP协议的客户端转换为本地Mac OS X框架。 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). 使用这些功能时,我可以与在MS Windows(或Wine)下运行的服务器建立有效的连接(尽管似乎我需要以与Winsocks相同的方式处理ECONNREFUSED)。

I can also pass the created socket to CFStreamCreatePairWithSocket to obtain a functional NSInputStream, NSOutputStream pair: 我还可以将创建的套接字传递给CFStreamCreatePairWithSocket以获得功能性的NSInputStream和NSOutputStream对:

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 目前,我仅设法使用以下方法获取功能正常的NSInputStream

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? 使用高级CFStream / NSStream框架可能无法使用精细控制(客户端和服务器端口规范,超时规范等)吗?

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. 我看到代码有点混乱,与InitCommClient位于C ++模块中一样,但是显然在继续之前的测试过程中,它的工作情况足够好。

Hope this helps - and feel free to dig through the full code . 希望这对您有所帮助-并可以随意浏览全部代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM