Можно ли использовать источник отправки GCD для создания асинхронного соединения() в сокете?

Вы можете использовать источники отправки GCD для чтения и записи из сокетов, отслеживать прослушивающий сокет для входящих подключений, но я не мог понять, как использовать источник отправки для подключения сокета?

В псевдокоде он выглядит примерно так:

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, connectingSocket, ...);
dispatch_source_set_event_handler(source, ^{
 // Socket did connect or not
});
fcntl(connectingSocket, F_SETFL, O_NONBLOCK);
connect(connectingSocket, addr, len);
dispatch_source_resume(source);

Это было бы лучше, чем использовать select().

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
</arpa></netinet></sys></sys>

licensed under cc by-sa 3.0 with attribution.