MonoTouch和CFStream API的问题

时间:2012-09-27 14:13:30

标签: ios xamarin.ios ios-simulator cfstream cfsocket

我目前正在开发一个需要通过套接字连接与MQTT服务器通信的应用程序。由于System.Net.Sockets API在从WiFi网络切换到3G网络时往往行为不端(实际上这种情况发生了很多)我决定尝试使用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永远不会被触发,{{1始终为false,任何写入尝试都会因超时而失败。

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); 创建一对流是唯一一个实际生成一对我可以使用的流:开放不会崩溃,我可以分别写入和读取。

API在模拟器和实际设备上都以这种方式运行。那么,这是我做错了吗?这是MonoTouch问题吗?这是CFStream API本身的错误吗?

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

2 个答案:

答案 0 :(得分:1)

我在MonoMac / MonoTouch中写了大部分CFNetwork代码,所以我希望能够帮助你: - )

您的代码对我来说没问题。它适用于MonoMac(Mac上的独立Cocoa应用程序),但我发现MonoTouch存在同样的问题。打开读取流有时会起作用,有时候不会打开写入流总是失败。

CFStream.CreatePairWithSocketToHost()来电CFStreamCreatePairWithSocketToCFHost()

添加新的重载版本后:

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

调用CFStreamCreatePairWithSocketToHost(),现在工作正常。

我刚看了一眼,发现了问题,很快就会解决它。

关于你的第二个问题,CFSocket API在内部遇到相同的代码路径,所以它也受到这个bug的影响。

答案 1 :(得分:0)