V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
NUT
V2EX  ›  iDev

请教一个关于在 NSURLConnection 使用 NSInputStream 的问题

  •  
  •   NUT · 2014-04-19 13:42:32 +08:00 · 4439 次点击
    这是一个创建于 3873 天前的主题,其中的信息可能已经有所发展或是发生改变。
    因为项目需求,我需要建立一个Connection连接,上层类通过该连接不断向服务器发送buffer。因为连接数限制,不能使用socket,要求采用http。目前我使用NSMutableURLRequest 中setHTTPBodyStream 的方法。

    我现在的代码思路是在
    1.初始化一个NSInputStream,然后设置代理并且加入runloop
    2.在Request把InputStream 加进去。
    3.建立连接。
    4.等待NSInputStream的回调方法,然后加入数据。

    代码
    NSMutableData *mutableData = [NSMutableData dataWithLength:uploadData.length];
    self.inputStream = [NSInputStream inputStreamWithData:mutableData];
    self.inputStream.delegate =self;
    [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [self.inputStream open];
    [request setHTTPBodyStream:self.inputStream];

    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];

    // delegate
    - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
    switch (eventCode) {
    case NSStreamEventOpenCompleted: {
    NSLog(@"producer stream opened");
    } break;
    case NSStreamEventHasBytesAvailable: {
    // 这里写入buffer
    NSLog(@"NSStreamEventHasBytesAvailable");
    }
    }

    现在的问题:
    1.初始化流时,发送Stream的大小是否为初始化传入Data的大小?
    NSMutableData *mutableData = [NSMutableData dataWithLength:uploadData.length];
    self.inputStream = [NSInputStream inputStreamWithData:mutableData];
    2.我打印日志发现connection是在流写入完成之后然后才建立连接发送数据的。能否做到先建立Connection然后自己主动调用Stream同步方法往里面写数据,这时候已经开始传入数据了(现在使用的是stream的回调方法)?

    这里先谢谢各位大牛。:D
    第 1 条附言  ·  2014-04-23 21:04:00 +08:00
    已经解决了。
    苹果提供了SimpleURLConnections 这个示例代码。
    我使用iOS底层CFStreamCreatePairWithSocket接管上层NSInputStream,实现边发送边上传。
    10 条回复    2015-05-22 08:59:52 +08:00
    alexrezit
        1
    alexrezit  
       2014-04-19 13:55:59 +08:00 via iPhone
    用 AFNetworking 吧...
    NUT
        2
    NUT  
    OP
       2014-04-19 14:01:40 +08:00
    @alexrezit 公司不让用第三方库......
    alexrezit
        3
    alexrezit  
       2014-04-19 14:15:58 +08:00 via iPhone
    @NUT
    辭職.
    NUT
        4
    NUT  
    OP
       2014-04-19 15:54:39 +08:00
    @alexrezit 我勒个大擦...这是解决问题的根本啊! 不过刚回西安还是先稳稳再说。
    BB9z
        5
    BB9z  
       2014-04-20 22:49:22 +08:00
    但 copy 一个 1.x 的 AFURLConnectionOperation 吧。
    NUT
        6
    NUT  
    OP
       2014-04-23 21:01:31 +08:00
    @BB9z 我最后实现了,用底层的c接口。
    MartinTsao
        7
    MartinTsao  
       2014-05-03 23:14:33 +08:00
    @NUT
    你好,我现在也遇到此类问题,我需要做到的是边下载边上传.
    对于CFStreamCreatePairWithSocket的使用我没有摸清思路,请问能帮助一下我吗?
    NUT
        8
    NUT  
    OP
       2014-05-22 15:48:45 +08:00
    @MartinTsao
    边下载边上传。你还是建立2条连接比较好。也就是一个是上行,一个下行。
    我这边测试的结果,NSURLConnection 只有把数据上传完以后才会给你返回response。

    CFStreamCreatePairWithSocket 你可以看看 苹果官方示例, SimpleURLConnections 的PostController.m 文件。 你外层向流写入数据的时候,可以不用等他回调,可以直接写。
    alison123456
        9
    alison123456  
       2015-05-21 17:41:31 +08:00
    你好,我遇到相同问题。看了官方例子的代码,对于CFStreamCreatePairWithSocket 用法不太理解,例子中实现了NSoutputStream的委托,而没有对NSInputStream继续读入要发送的buffer。楼主是采用的官方例子中方法解决问题的吗?能不能指点一下,谢谢!
    NUT
        10
    NUT  
    OP
       2015-05-22 08:59:52 +08:00
    @alison123456

    简单点说就是, CFStreamCreatePairWithSocket 关联一对stream (InputStreamOne ,OutputStreamOne),然后把 OutputStreamOne 的指针赋给 HTTPRequest 的 InputStream ,需要写数据就直接向 关联管道的InputStreamOne来写。因为代理方法是一样的 - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode ,所以根据 [ aStream isEqual:InputStreamOne]
    来决定是否写入,需要注意的坑是 需要把这些 InputStreamOne OutputStreamOne 都加入runloop里面,如果发送完毕数据 必须手动关闭InputStreamOne,否则你永远不会上传完成。

    另可以通过cfnetwork那层来实现,总体来比较简单,可以看看 webscoket ios 实现的代码。

    希望对你有用。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1329 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 23:36 · PVG 07:36 · LAX 15:36 · JFK 18:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.