2012-09-27 39 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 –