Ответ 1
Я изначально неправильно разобрал ваш вопрос... извините. Я получаю это сейчас... вы хотите получить EINPROGRESS
от connect
и указать источник отправки, когда вызов connect
требует внимания вместо опроса с помощью select
... Это было довольно легко взломать, и, как представляется, работает:
#import <sys/types.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
@implementation AppDelegate
{
dispatch_source_t foo;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
int socketFD = socket(PF_INET, SOCK_STREAM, 0);
if (socketFD == -1)
{
socketFD = -1;
abort();
}
int flags = fcntl(socketFD, F_GETFL, 0);
int status = fcntl(socketFD, F_SETFL, flags | O_NONBLOCK);
if (status == -1)
{
close(socketFD);
socketFD = -1;
abort();
}
struct sockaddr_in sockaddr4 = {0};
sockaddr4.sin_len = sizeof(sockaddr4);
sockaddr4.sin_family = AF_INET;
sockaddr4.sin_port = htons(22);
inet_aton("127.0.0.1", &sockaddr4.sin_addr);
foo = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, socketFD, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler(foo, ^{
if (connect(socketFD, (const struct sockaddr *)&sockaddr4, (socklen_t)sizeof(sockaddr4)))
{
int err = errno;
NSLog(@"errno: %s", strerror(err));
if (err == ECONNREFUSED)
{
abort();
}
else if (err == EISCONN)
{
// connected -- queue up other work
DoStuff();
// Cancel the source so it doesnt keep notifying...
dispatch_source_cancel(foo);
}
}
});
dispatch_source_set_cancel_handler(foo, ^{
NSLog(@"Cancel");
});
dispatch_resume(foo);
// Do initial connect
if (connect(socketFD, (const struct sockaddr *)&sockaddr4, (socklen_t)sizeof(sockaddr4)))
{
if(errno != EINPROGRESS)
{
close(socketFD);
socketFD = -1;
abort();
}
}
}
@end