zoukankan      html  css  js  c++  java
  • 宋体、代码iOS网络编程实践NSStream实现TCP Socket iPhone客户端by小雨

    首先声明,我是一个菜鸟。一下文章中出现技术误导情况盖不负责

        客户端我们用应iPhone用应程序,画面比较简单。点击发送钮按,给服务器发送一些字符串去过。点击接收钮按就会从服务器读取一些字符串,并且示显在画面上。

        

        2

        有关客户端用应的UI部份不再绍介了,我们直接看代码部份,Socket客户端可以用采CFStream或NSStream实现。为了给读者绍介更多的知识,本例我们用采NSStream实现。NSStream实现用采Objective-C语言,一些面向对象的类。

        上面我们看看客户端视图控制器ViewController.h

    #import <CoreFoundation/CoreFoundation.h>
    
    #include <sys/socket.h>
    
    #include <netinet/in.h>
    
     
    
    #define PORT 9000
    
     
    
    @interface ViewController : UIViewController<NSStreamDelegate>
    
    {
    
    int flag ; //操纵志标 0为发送 1为接收
    
    }
    
     
    
    @property (nonatomic, retain) NSInputStream *inputStream;
    
    @property (nonatomic, retain) NSOutputStream *outputStream;
    
     
    
    @property (weak, nonatomic) IBOutlet UILabel *message;
    
     
    
    - (IBAction)sendData:(id)sender;
    
    - (IBAction)receiveData:(id)sender;
    
     
    
    @end

        定义属性inputStream和outputStream,它们输入流NSInputStream和出输流NSOutputStream类。它们与服务器CFStream实现中的输入流CFReadStreamRef和出输流CFWriteStreamRef对应的。

        视图控制器ViewController.m的初始化网络法方initNetworkCommunication代码:

    - (void)initNetworkCommunication
    
    {
    
    CFReadStreamRef readStream;
    
    CFWriteStreamRef writeStream;
    
    CFStreamCreatePairWithSocketToHost(NULL,
    
    (CFStringRef)@”192.168.1.103″, PORT, &readStream, &writeStream);   ①
    
    _inputStream = (__bridge_transfer NSInputStream *)readStream; ②
    
    _outputStream = (__bridge_transfer NSOutputStream*)writeStream;  ③
    
    [_inputStream setDelegate:self];  ④
    
    [_outputStream setDelegate:self];  ⑤
    
    [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    
    forMode:NSDefaultRunLoopMode]; ⑥
    
    [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
    
    forMode:NSDefaultRunLoopMode];  ⑦
    
    [_inputStream open];  ⑧
    
    [_outputStream open];  ⑨
    
    }
    
    点击发送和接收钮按发触的法方如下:
    
    /* 点击发送钮按  */
    
    - (IBAction)sendData:(id)sender {
    
    flag = 0;
    
    [self initNetworkCommunication];
    
    }
    
    /* 点击接收钮按  */
    
    - (IBAction)receiveData:(id)sender {
    
    flag = 1;
    
    [self initNetworkCommunication];
    
    }

        它们都调用initNetworkCommunication法方,并置设操纵识标flag,如果flag0发送数据,flag1接收数据。

        流的状态的变更发触很多事件,并调回NSStreamDelegate协议中定义的法方stream:handleEvent:,其代码如下:

    -(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
    
    NSString *event;
    
    switch (streamEvent) {
    
    case NSStreamEventNone:
    
    event = @”NSStreamEventNone”;
    
    break;
    
    case NSStreamEventOpenCompleted:
    
    event = @”NSStreamEventOpenCompleted”;
    
    break;
    
    case NSStreamEventHasBytesAvailable:
    
    event = @”NSStreamEventHasBytesAvailable”;
    
    if (flag ==1 && theStream == _inputStream) {
    
    NSMutableData *input = [[NSMutableData alloc] init];
    
    uint8_t buffer[1024];  ①
    
    int len;
    
    while([_inputStream hasBytesAvailable]) ②
    
    {
    
    len = [_inputStream read:buffer maxLength:sizeof(buffer)];  ③
    
    if (len > 0)
    
    {
    
    [input appendBytes:buffer length:len];
    
    }
    
    }
    
    NSString *resultstring = [[NSString alloc]
    
    initWithData:input encoding:NSUTF8StringEncoding];
    
    NSLog(@”接收:%@”,resultstring);
    
    _message.text = resultstring;
    
    }
    
    break;
    
    case NSStreamEventHasSpaceAvailable:
    
    event = @”NSStreamEventHasSpaceAvailable”;
    
    if (flag ==0 && theStream == _outputStream) {
    
    //出输
    
    UInt8 buff[] = ”Hello Server!”; ④
    
    [_outputStream write:buff maxLength: strlen((const char*)buff)+1]; ⑤
    
    //关闭出输流
    
    [_outputStream close];
    
    }
    
    break;
    
    case NSStreamEventErrorOccurred:
    
    event = @”NSStreamEventErrorOccurred”;
    
    [self close]; ⑥
    
    break;
    
    case NSStreamEventEndEncountered:
    
    event = @”NSStreamEventEndEncountered”;
    
    NSLog(@”Error:%d:%@”,[[theStream streamError] code],
    
    [[theStream streamError] localizedDescription]);
    
    break;
    
    default:
    
    [self close];  ⑦
    
    event = @”Unknown”;
    
    break;
    
    }
    
    NSLog(@”event——%@”,event);
    
    }

        在读取数据分支(NSStreamEventHasBytesAvailable)中,代码第①为行读取数据预备缓冲区,本例中置设的是1024个字节,这个小大会对流的读取有很多的影响。第②行代码用应hasBytesAvailable法方判断是不是流有数据可以读,如果有可读数据就进行循环读取。第③行代码用应流的read:maxLength:法方读取数据到缓冲区,第1个数参是缓冲区对象buffer,第2个数参是读取的缓冲区的字节长度。

        在入写数据分支(NSStreamEventHasSpaceAvailable)中,代码第④行是要入写的数据,第⑤行代码[_outputStream write:buff maxLength: strlen((const char*)buff)+1]是写如数据法方。

        第⑥和第⑦行代码[self close]调用close法方关闭,close法方代码如下:

    -(void)close
    
    {
    
    [_outputStream close];
    
    [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
    
    forMode:NSDefaultRunLoopMode];
    
    [_outputStream setDelegate:nil];
    
    [_inputStream close];
    
    [_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
    
    forMode:NSDefaultRunLoopMode];
    
    [_inputStream setDelegate:nil];
    
    }

    文章结束给大家分享下程序员的一些笑话语录: 问路
    有一个驾驶热气球的人发现他迷路了。他降低了飞行的高度,并认出了地面 上的一个人。他继续下降高度并对着那个人大叫,“打扰一下,你能告诉我我 在哪吗?”
    下面那个人说:“是的。你在热气球里啊,盘旋在 30 英尺的空中”。
    热气球上的人说:“你一定是在 IT 部门做技术工作”。
    “没错”,地面上的人说到,“你是怎么知道的?”
    “呵呵”,热气球上的人说,“你告诉我的每件事在技术上都是对的,但对都没 有用”。
    地面上的人说,“你一定是管理层的人”。
    “没错”,热气球上的人说,“可是你是怎么知道的?”
    “呵呵”,地面上的那人说到,“你不知道你在哪里,你也不知道你要去哪,你 总希望我能帮你。你现在和我们刚见面时还在原来那个地方,但现在却是我 错了”。

  • 相关阅读:
    iPhone网络编程之--Reachability
    ASIHTTPRequest 详解, http 请求终结者2
    什么情况下使用break关键字? 什么情况下使用Continue关键字? Java如何声明一个数组?JS如何声明一个数组?如何获取数组长度? 如何遍历数组?
    说说三元运算和if...else的相同之处? Switch语句的条件只能接受什么类型的值? 说说do...while和while的区别? 说说for循环的两种写法?
    String类的常用方法
    逻辑结算的结果是什么类型? 比较运算的值是什么类型? 声明字符串有哪几种方式?怎么写? Math类有哪些常用的方法? 三元运算怎么写?
    算术运算有哪些?逻辑运算有哪些?比较运算有哪些?
    Java中8种基本数据类型是哪些?
    Java如何声明变量?JS如何声明变量?
    回顾之前知识: 注释
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3022903.html
Copyright © 2011-2022 走看看