2010-02-16 36 views
1

我正在寫一個可可應用程序。在應用程序中有一個套接字,每當套接字變得可讀時,我想從套接字讀取數據,處理數據並相應地更新用戶界面。我想在主循環中集成讀取事件檢查,即我想將套接字附加到主循環,並讓主循環在套接字變得可讀時調用回調。OS X:如何使用NSRunLoop監視套接字讀取事件?

我寫了一個測試程序,但由於某種原因它不工作:

#include <stdio.h> 
#include <Foundation/NSAutoReleasePool.h> 
#include <Foundation/NSRunLoop.h> 
#include <Foundation/NSPort.h> 

@interface MyDelegate : NSObject <NSPortDelegate> { 
} 
- (void)handlePortMessage:(NSPortMessage *)portMessage; 
@end 

@implementation MyDelegate 
- (void)handlePortMessage:(NSPortMessage *)portMessage { 
    printf("Haiz\n"); 
} 
@end 

int 
main() { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSSocketPort *server = [NSSocketPort alloc]; 
    MyDelegate *foo = [MyDelegate alloc]; 
    [server initWithTCPPort: 1234]; 
    [server setDelegate: foo]; 
    [[NSRunLoop mainRunLoop] addPort: server forMode: NSDefaultRunLoopMode]; 
    [[NSRunLoop mainRunLoop] run]; 
    [pool release]; 
    return 0; 
} 

的應用程序應該監聽本地主機端口1234,每當有人連接到服務器或發送數據到服務器,應用程序應該在控制檯上打印「Haiz」。然而,該應用程序什麼也沒有做。套接字已創建,我可以telnet到端口1234,但該應用程序不會將任何內容打印到控制檯。

我在做什麼錯?

+0

其中,發送alloc到一個類,但不發送init到實例。你用MyDelegate對象完全忘記了這一點,這很好地證明了爲什麼你總是應該在同一個消息表達式中保留'alloc'和'init':MyDelegate * foo = [[[MyDelegate alloc] init] autorelease];'也請注意您必須釋放您分配的對象。查看內存管理規則:http://developer.apple.com/mac/library/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html –

回答

1

從文檔:

一個NSSocketPort對象可被用作分佈式對象連接的端點。

這不是你在這裏做的。

你想要或者NSFileHandle圍繞來自BSD套接字API的套接字文件描述符或 a CFSocket。這會讓你把套接字放在運行循環中。

+0

NSFileHandle不是NSPort,並且沒有CFRunLoopSource,因此我無法附加它到主循環。 – Hongli

+0

我知道NSFileHandle不是NSPort。 NSPorts適用於IPC。您的委託方法不會被調用,因爲您永遠不會在該套接字上收到端口消息。至於附加到運行循環,請發送文件句柄'acceptConnectionInBackgroundAndNotify'消息或使用CFSocket代替。 –

+0

我的印象是FoundationKit只是CoreFoundation的一個客觀的C封裝,但現在看起來它們完全不同,並且我可以用CoreFoundation做一些事情,但不能用FoundationKit做什麼? 我試圖堅持FoundationKit的原因是因爲我實際上是在MacRuby中編寫應用程序,而不是Objective C,並且它對CoreFoundation API期望的函數指針有一些問題。 – Hongli

0

您希望以您所使用的方式使用NSSocketPort,但創建一個NSFileHandle以接受套接字上的連接。您可以在主線程上獲得回調,就像您期待的一樣,首先進行新的連接,然後再獲得關於這些連接的數據。使用這個O'Reilly article,並忽略HTTP的東西。