2012-09-27 75 views
2

我目前正在開發一個需要通過套接字連接與MQTT服務器進行通信的應用程序。由於System.Net.Sockets API在從WiFi網絡切換到3G網絡時往往會出現問題(實際上這種情況非常多),所以我決定嘗試使用CFStream API。這樣做我遇到了幾個問題,如下所示。MonoTouch和CFStream API的問題

一旦我在任何一個流上調用Open(),立即創建一對包含CreatePairWithSocketToHost的流。

CFStream.CreatePairWithSocketToHost(GetEndPoint(), out mReadStream, out mWriteStream); 
mReadStream.EnableEvents(CFRunLoop.Current, CFRunLoop.CFDefaultRunLoopMode); 
mWriteStream.EnableEvents(CFRunLoop.Current, CFRunLoop.CFDefaultRunLoopMode); 
mReadStream.Open(); 
mWriteStream.Open(); 

無論我是否撥打EnableEvents(),都會發生崩潰。唯一的例外是:

[ERROR] FATAL UNHANDLED EXCEPTION: MonoTouch.CoreFoundation.CFException: The operation couldn’t be completed. Cannot allocate memory 
    at MonoTouch.CoreFoundation.CFStream.CheckError() [0x0000f] in /Developer/MonoTouch/Source/monotouch/src/shared/CoreFoundation/CFStream.cs:236 
    at MonoTouch.CoreFoundation.CFStream.Open() [0x00040] in /Developer/MonoTouch/Source/monotouch/src/shared/CoreFoundation/CFStream.cs:248 
    at TestCfNework.RootViewController.TestCreatePairToHost() [0x00041] in /Users/adrian/Projects/TestCfNework/TestCfNework/RootViewController.cs:79 
    at TestCfNework.RootViewController.ViewDidLoad() [0x00000] in /Users/adrian/Projects/TestCfNework/TestCfNework/RootViewController.cs:24 
    at MonoTouch.UIKit.UIWindow.MakeKeyAndVisible() [0x00008] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIWindow.g.cs:124 
    at TestCfNework.AppDelegate.FinishedLaunching (MonoTouch.UIKit.UIApplication app, MonoTouch.Foundation.NSDictionary options) [0x0002e] in /Users/adrian/Projects/TestCfNework/TestCfNework/AppDelegate.cs:32 
    at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 
    at TestCfNework.Application.Main (System.String[] args) [0x00000] in /Users/adrian/Projects/TestCfNework/TestCfNework/Main.cs:17 

創建具有CreatePairWithSocket一對流首先創建和連接CFSocket允許Open()沒有崩潰繼續,但CanAcceptBytesEvent是從來沒有發射,CanAcceptBytes()始終是假的,任何寫入失敗了時間到。

mSocket = new CFSocket(AddressFamily.InterNetwork, 
    SocketType.Stream, 
    ProtocolType.Tcp, 
    CFRunLoop.Current); 
mSocket.ConnectEvent += delegate { 
    Console.WriteLine("Socket connected"); 

    CFStream.CreatePairWithSocket(mSocket, out mReadStream, out mWriteStream); 
    mReadStream.EnableEvents(CFRunLoop.Current, CFRunLoop.CFDefaultRunLoopMode); 
    mWriteStream.EnableEvents(CFRunLoop.Current, CFRunLoop.CFDefaultRunLoopMode); 

    mReadStream.Open(); 
    mWriteStream.Open(); 

    mWriteStream.CanAcceptBytesEvent += delegate { 
     Console.WriteLine("Write stream can now accept data"); 
    }; 
    mWriteStream.ErrorEvent += delegate { 
     Console.WriteLine(mWriteStream.GetError()); 
    }; 
}; 
mSocket.Connect(GetEndPoint(), 0); 

創建一個對使用CreatePairWithPeerSocketSignature流的是實際產生一對,我可以工作流的只有一個:開放不會崩潰,我允許寫入和讀取各個。

API在模擬器和實際設備上的行爲都是這樣。所以,這是我做錯了什麼?這是MonoTouch的問題嗎?它是CFStream API本身的錯誤嗎?

MonoTouch版本:6.0.1。 XCode版本:4.5。

+0

想知道您最終使用哪個MQTT庫,還是正在開發自己的? –

+1

這兩個,實際上:我目前使用這個庫http://sourceforge.net/projects/mqttdotnet/(雖然它需要一些調整),同時我正在開發自己的。 – AlexB

+0

啊是的我猜這個庫不符合3.1。很想在某個階段看到你的圖書館,如果適合,很樂意列在mqtt.org網站上。 –

回答

1

我寫的大部分CFNetwork的代碼中的MonoMac/MonoTouch的,所以我應該有希望能夠幫助您完成此:-)

您的代碼對我來說看起來沒問題。它適用於MonoMac(Mac上的獨立Cocoa應用程序),但是我看到了與MonoTouch相同的問題。打開讀取流有時會起作用,有時不會,打開寫入流總是失敗。

CFStream.CreatePairWithSocketToHost()來電CFStreamCreatePairWithSocketToCFHost()

添加新的重載版本後:

public static void CreatePairWithSocketToHost (string host, int port, 
                out CFReadStream readStream, 
                out CFWriteStream writeStream) 

這就要求CFStreamCreatePairWithSocketToHost(),這是現在工作的罰款。

我剛看過這個,發現問題,很快就會有修復。

關於你的第二個問題,CFSocket API在內部實現了相同的代碼路徑,所以它也受到這個錯誤的影響。

+0

這應該解決它:https://github.com/mono/maccore/commit/5f191fb249426435d5ab0bc6ab06dae241be2563 –