zoukankan      html  css  js  c++  java
  • iOS 基于Socket 的 C/S 网络通信结构(下一个)

                 以前实现简单 Server 程序,服务端通过 void WriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void* clientCallBackInfo) 函数向client发送“你好。client!”的消息,假设client接收成功的话就会显示“你好。client!

    ”。须要显示服务端发送过来的消息。那么就须要定义一个UILabel输出口(IBOutlet)来显示消息;client还须要加入两个button,一个用来接收服务端消息的动作事件方法 receiveData:和发送client“收到啦,服务端”消息的动作事件方法 sendData:;加入关联就能够了,比較简单,以下来看一下详细实现的代码:

         ViewController.h

    #import <UIKit/UIKit.h>
    
    #import <CoreFoundation/CoreFoundation.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #define PORT 8734       //将端口设置为8734。能够依据详细情况改变
    
    @interface ViewController : UIViewController<NSStreamDelegate>
    {
        int flag ; //操作标志 0为发送 1为接收
    }
    
    @property (nonatomic, retain) NSInputStream *inputStream;
    @property (nonatomic, retain) NSOutputStream *outputStream;
    
    @property (weak, nonatomic) IBOutlet UILabel *message;    //在client显示来自服务端的消息
    
    - (IBAction)sendData:(id)sender;      //发送client的消息
    - (IBAction)receiveData:(id)sender;   //接收来自服务端的消息
    
    @end
          ViewController.m

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
    }
    
    //初始化client网络连接
    - (void)initNetworkCommunication
    {
        
        CFReadStreamRef readStream;
        CFWriteStreamRef writeStream;
        //这里须要填写 IP 地址,依据自己路由能够用的 IP来定,这里是192.168.1.103,假设不知道能够下载 IP 扫描器
        CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.1.103", PORT, &readStream, &writeStream);
        
        self.inputStream = (__bridge_transfer NSInputStream *)readStream;  //将CFStream对象转化为NSStream对象
        self.outputStream = (__bridge_transfer NSOutputStream
                         *)writeStream;              //将CFStream对象转化为NSStream对象
        [self.inputStream setDelegate:self];
        [self.outputStream setDelegate:self];
        [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                                forMode:NSDefaultRunLoopMode];    //NSStream 方法 scheduleInRunLoop: 设置 Run Loop
        [self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                                 forMode:NSDefaultRunLoopMode];
        [self.inputStream open];   //NSStream 的 open 方法来打开数据流对象
        [self.outputStream open];
        
    }
    
    //关闭数据流操作
    -(void)close
    {
        [self.outputStream close];
        [self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [self.outputStream setDelegate:nil];
        [self.inputStream close];
        [self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [self.inputStream setDelegate:nil];
    }
    
    //从client发送数据事件方法
    - (IBAction)sendData:(id)sender {
        flag = 0;   //表示发送
        [self initNetworkCommunication];
        
    }
    
    //从服务端接收数据事件方法
    - (IBAction)receiveData:(id)sender {
        flag = 1;   //表示接收
        [self initNetworkCommunication];
        
    }
    
    -(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[2048]; //读取数据准备缓冲区,本例中设置的是2048字节,这个大小会对流的读取有非常大影响   
                    int len;
                    while([self.inputStream hasBytesAvailable])
                    {
                        len = [self.inputStream read:buffer maxLength:sizeof(buffer)];  //读取数据到缓冲区
                        if (len > 0)
                        {
                            [input appendBytes:buffer length:len];
                        }
                    }
                    NSString *resultstring = [[NSString alloc] initWithData:input encoding:NSUTF8StringEncoding];
                    NSLog(@"接收:%@",resultstring);
                    self.message.text = resultstring;
                }
                break;
            case NSStreamEventHasSpaceAvailable:   //这个流能够接收数据的写入,在写数据时使用
                event = @"NSStreamEventHasSpaceAvailable";
                if (flag ==0 && theStream == _outputStream) {
                    //输出
                    UInt8 buff[] = "收到啦,服务端。";       //向服务端发送的消息
                    [self.outputStream write:buff maxLength: strlen((const char*)buff)+1];   //向服务端写入数据方法
                     //必须关闭输出流否则,server端一直读取不会停止。
                    [self.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;
        }
    
    }
    
    @end
    
                  从代码能够知道。client採用的是 APPLE 自家的 NSStream 来实现的,都是比較简单的基本数据流操作。

         微笑如有哪些不正确的地方,欢迎指出!



    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    C++中char*,String,int,CString间转换
    获取本地MAC地址和多IP
    子窗口
    linux记录键盘
    curses和窗口
    使用curses函数写的hello world 程序
    Java 复习笔记
    Ubuntu apt install 下载软件很慢的解决办法
    Ubuntu python多个版本管理
    VMware下的Ubuntu16设置连接主机网络,设置主机下可以通过xshell访问 VMware下的Ubuntu
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4800455.html
Copyright © 2011-2022 走看看