iOS -- 原生NSStream实现socket

- (void)startSocket:(NSString *)address andPort:(int)port
{
    CFReadStreamRef readRef;
    CFWriteStreamRef writeRef;

    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)address, port, &readRef, &writeRef);

    _inputStream = (__bridge NSInputStream *)readRef;
    _outputStream = (__bridge NSOutputStream *)writeRef;

    // 设置流属性
    [_inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];
    [_outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];

    // 设置代理
    _inputStream.delegate = self;
    _outputStream.delegate = self;

    // 放到runloop中
    [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [_inputStream open];
    [_outputStream open];
}

// 断开 scoket 连接
- (void)closeSocket {
    if(_inputStream){
        _inputStream.delegate = nil;
        [_inputStream close];
        [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        _inputStream = nil;
    }
    if(_outputStream){
        _outputStream.delegate = nil;
        [_outputStream close];
        [_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        _outputStream = nil;
        [SVProgressHUD showSuccessWithStatus:@"断开连接成功"];
    }
    // 通知给界面
    [[NSNotificationCenter defaultCenter] postNotificationName:@"closeSocket" object:nil userInfo:nil];
}

// 代理的回调是在主线程
#pragma mark - <NSStreamDelegate>代理方法
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode) {
        case NSStreamEventNone:
            break;
        case NSStreamEventOpenCompleted:
            [SVProgressHUD showSuccessWithStatus:@"连接成功"];
            NSLog(@"成功建立连接, 形成输入输出管道");
            break;
        case NSStreamEventHasBytesAvailable:
            NSLog(@"有数据可读");
        {
            uint8_t buf[3072];
            NSInteger len = 0;
            NSInputStream *inputStream = (NSInputStream *)aStream;
            len = [inputStream read:buf maxLength:3072];

            if (len) {
                _tempString = [NSMutableString string];
                // 将16进制字符拼接起来
                for (int i = 0; i < len; i++) {
                    NSMutableString *str = [NSMutableString stringWithFormat:@"%x", buf[i]];
                    if (str.length < 2) {
                        [str insertString:@"0" atIndex:0];
                    }
                    [_tempString appendString:str];
                }
                // 进行分包丶 粘包处理, 同时进行KVO监听可用的包

                    [_stick_Subcontract_Package HandleResultOnReceiveData:_tempString];

            }
            break;
        }
        case NSStreamEventHasSpaceAvailable:
            NSLog(@"可以发送数据");
            break;
        case NSStreamEventErrorOccurred:
            NSLog(@"有错误发生, 连接失败");
            [SVProgressHUD showErrorWithStatus:@"连接错误"];
        {
            [aStream close];
            break;
        }
        case NSStreamEventEndEncountered:
            [SVProgressHUD showErrorWithStatus:@"正常断开连接"];
            NSLog(@"正常断开连接");

        {
            [aStream close];
            [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            aStream = nil;
            break;
        }

        default:
            break;
    }
}

有个问题, 就是这个没有实现异步接受消息.所以最好用asynSocket

时间: 2024-10-09 10:29:07

iOS -- 原生NSStream实现socket的相关文章

HTML5能取代IOS原生应用吗

介绍 移动应用程序(App)和HTML5都是目前最火的技术,二者之间也有不少重叠之处.在移动设备浏览器里运行的html5的web页面,也可以重新打包成不同平台上运行的app.目前很多浏览器都有很好的跨平台支持,(译注:firefox居然可以在android中使用和windows下同样的浏览器内核),HTML5的web方案,对开发者来说更为方便.完成一次,即可多平台使用.但这确实可行吗?仍然有许多必要原因,使得开发者选择了app开发.很明显,很多人已经在这么做了.本文将详细分析两种方案的优劣. 功

React Native iOS原生模块开发实战|教程|心得|如何创建React Native iOS原生模块

尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://blog.csdn.net/fengyuzhengfan/article/details/54691432) 前言 一直想写一下我在React Native原生模块封装方面的一些经验和心得,来分享给大家,但实在抽不开身,今天看了一下日历发现马上就春节了,所以就赶在春节之前将这篇博文写好并发布(其实是两篇:要看Android篇的点这里<React Native Android原生模块开发>). 我平时在用React Nativ

iOS原生CIFilter创建二维码

iOS原生CIFilter创建二维码 2016-05-31 未来C 关于二维码生成,网上也是有很多,很早以前的第三方库大多数都是通过C++写,也是有的如zxing,也是挺好用,这里介绍的是通过CIFilter创建二维码.   创建二维码非常简单,只要传入简单的字符串就好了 - (CIImage *)createQRForString:(NSString *)qrString { NSData *stringData = [qrString dataUsingEncoding:NSUTF8Stri

iOS项目开发之Socket编程

有一段时间没有认真总结和写博客了 前段时间找工作.进入工作阶段.比较少静下来认真总结,现在静下心来总结一下最近的一些心得 前言 AsyncSocket介绍 AsyncSocket详解 AsyncSocket示例 一.前言 公司的项目用到了Socket编程,之前在学习的过程当中,用到的更多的还是http请求的方式.但是既然用到了就必须学习一下,所以就在网上找一些例子,然后想自己写一个demo.可是发现很多写iOS Socket的博客并没有很详细的说明,也可能是大神们觉得其他东西都浅显易懂. 自己专

二维码扫描(iOS原生二维码扫描)

一.关于二维码扫描的第三方库有很多:例如比较常用的两个 1.ZBar SDK ZBar为我们提供了两种使用方式,一种是直接调用ZBar提供的ZBarReaderViewController打开一个扫描界面,另一种方式是使用ZBar提供的可以嵌在其他视图中的ZBarReaderView,实际项目中我们更可能会使用第二种方式,这可以让我们对界面做更多的定制,详细的百度查找相关文档来看. 2.ZXing(Github镜像地址)是一个开源的条码生成和扫描库(开源协议为Apache2.0).它不但支持众多

使用HTML5构建iOS原生APP(2)

本文转载至 http://ju.outofmemory.cn/entry/18807 有时候我们在内嵌的webview中希望点击一个链接之后,触发iOS原生事件,而不是webview内页面跳转(因为webview的跳转很生硬,而ajax+js模拟则不如原生segue平滑). 有时候我们希望在页面内consloe.log('log something')的时候在控制台里看到输出,但手机里没有控制台,所以我们希望可以利用xcode的控制台输出信息. 因为iOS没有提供API让我们直接用html或者j

JS调用Android、Ios原生控件

在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时,提高代码质量,实现两者在网页端代码的统一. 首先我们先看一下Ios调用JS的方法实现: //无参调用 function SwiftCallJs1(){} //有参调用 function SwiftCallJs2(name, message){} 紧接着我们看一下Android调用JS的方法实现: /

[调整] Firemonkey iOS 原生 Edit 改变框色或透明框

说明:iOS 原生 Edit 透明框 方法: 效果: 说明:iOS 原生 Edit 设定框色 适用:Berlin Firemonkey 代码修改说明: 请将源码 FMX.Edit.iOS.pas 复制到自己的工程目录里,再进行修改. 代码内 {+++> 代表我增加的代码 代码内 {---> 代表我删除的代码 未来新版 Delphi 可以自己将 {+++> {---> 移植到新版代码内 constructor TiOSNativeEdit.Create; begin inherite

iOS原生地图开发进阶——使用导航和附近兴趣点检索

iOS原生地图开发进阶——使用导航和附近兴趣点检索 iOS中的mapKit框架对国际化的支持非常出色.在前些篇博客中,对这个地图框架的基础用法和标注与覆盖物的添加进行了详细的介绍,这篇博客将介绍两个更加实用的功能的开发:线路导航与兴趣点搜索.前几篇博客的链接如下: 地图基础用法详解:http://my.oschina.net/u/2340880/blog/415360. 添加大头针与自定义标注:http://my.oschina.net/u/2340880/blog/415441. 添加地图覆盖