【day1201_UDPSocket】:utpsocket的使用

使用UDP网络传输,是一种无连接的传输协议,不安全,一般使用在监控视频中或QQ聊天中,该网络传输就向广播传播模式,一对多。

在ios中如何使用:

首先导入AsyncUdpSocket类,在项目中添加一个框架CFNetwork.framework

因为该类采用的MRC模式,所以导入该类后需要把在项目中把该类的.m文件上附加"-fno-objc-arc",也就是不使用arc模式

服务器端:

初始化准备工作

self.socketUdp = [[AsyncUdpSocket alloc] initWithDelegate:self]; // 1.创建udpSocket

    [self.socketUdp bindToPort: error:Nil]; // 2.绑定端口

    [self.socketUdp enableBroadcast:YES error:Nil];// 3.开启广播

    [self.socketUdp receiveWithTimeout:- tag:]; // 4.接收数据

在读取方法中读取数据

-(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port;

然后注意该方法只会在初始化工作中接收数据方法中执行一次,一般会在该方法中在次执行继续接收操作。

客户端:

初始化工作跟服务端一样

发送数据

[self.socketUdp sendData:data toHost:@"255.255.255.255" port:8000 withTimeout:-1 tag:0];

如果服务端回复数据,跟服务端一样的操作。

练习:模仿QQ聊天中的群聊功能。

界面中有发送数据的TextField控件和button控件,有显示所有人发送信息的textView和显示所有人IP的tableView,还有一个switch开关如果开启则是对所有人说话,选择tableView中的某一个ip关闭switch进行私聊。

思路步骤:

1.开timer没隔5秒往整个网段发送"谁在线"

2.在接收数据那里如果接收到"谁在线"立即给该host回复"我在线"

3.如果收到"我在线" 把此host显示在tableview中

代码:

- (void)viewDidLoad

{

    [super viewDidLoad];

    self.hosts = [NSMutableArray array];

    [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(sendMessage) userInfo:Nil repeats:YES];

    self.socketUdp = [[AsyncUdpSocket alloc] initWithDelegate:self]; // 1.创建udpSocket

    [self.socketUdp bindToPort: error:Nil]; // 2.绑定端口

    [self.socketUdp enableBroadcast:YES error:Nil];// 3.开启广播

    [self.socketUdp receiveWithTimeout:- tag:]; // 4.接收数据

}

// 1.开timer没隔5秒往整个网段发送"谁在线"

// 2.在接收数据那里如果接收到"谁在线"立即给该host回复"我在线"

// 3.如果收到"我在线" 把此host显示在tableview中

-(void)sendMessage{

    NSString *str = @"谁在线";

    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

    // 发送数据

    [self.socketUdp sendData:data toHost:@"255.255.255.255" port: withTimeout:- tag:];

}

-(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{

    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    if ([host hasPrefix:@":"]) { // 如果是ipv6什么都不做

        return YES;

    }

    if (![str isEqualToString:@"谁在线"] && ![str isEqualToString:@"我在线"]) {

        self.textView.text = [self.textView.text stringByAppendingFormat:@"%@说:%@\n",host,str]; // 其他人说的话

    }

    if ([str isEqualToString:@"谁在线"]) {

        NSString *str = @"我在线";

        NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

        [self.socketUdp sendData:data toHost:host port: withTimeout:- tag:];

    }

    if ([str isEqualToString:@"我在线"]) {

        if (![self.hosts containsObject:host]) {

            [self.hosts addObject:host];

            [self.tableView reloadData];

        }

    }

    [self.socketUdp receiveWithTimeout:- tag:]; // 接收数据

    return YES;

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return self.hosts.count;

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *cellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    }

    cell.textLabel.text = self.hosts[indexPath.row];

    cell.textLabel.font = [UIFont systemFontOfSize:];

    return cell;

}

- (IBAction)click:(id)sender {

    if (self.switchs.isOn) { // 我对所有人说

        NSString *str = self.texiField.text;

        NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

        // 发送数据

        [self.socketUdp sendData:data toHost:@"255.255.255.255" port: withTimeout:- tag:];

        self.textView.text = [self.textView.text stringByAppendingFormat:@"我对所有人说:%@\n",str];

    }else{

        // 私聊

        NSString *str = self.texiField.text;

        NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

        // 发送数据

        [self.socketUdp sendData:data toHost:self.hostStr port: withTimeout:- tag:];

        self.textView.text = [self.textView.text stringByAppendingFormat:@"我对%@说:%@\n",self.hostStr,str];

    }

}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    self.hostStr = self.hosts[indexPath.row];

    self.switchs.on = NO;

}

【day1202_GameUDPSocket】:用udpsocket做的单机游戏用户交互

该案例需求:界面中有两个按钮分别是创建主机、加入游戏

点击创建主机后(空间)等待用户加入,如果有用户加入同意并跳转到开始游戏界面

点击加入游戏进入主机(空间)列表界面,点击某个等待对方同意,同意后跳转到开始游戏界面

创建主机代码:

- (void)viewDidLoad

{

    [super viewDidLoad];

    self.socketUdp = [[AsyncUdpSocket alloc] initWithDelegate:self]; // 初始化

    [self.socketUdp bindToPort: error:Nil]; // 绑定端口

    [self.socketUdp enableBroadcast:YES error:Nil]; // 开启广播

    [self.socketUdp receiveWithTimeout:- tag:]; // 读取数据

}

// 读取数据

-(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{

    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    if ([str isEqualToString:@"有主机吗"]) {

        NSLog(@"str:%@,host:%@",str,host);

        NSString *str = @"有"; // 回复

        [self.socketUdp sendData:[str dataUsingEncoding:NSUTF8StringEncoding] toHost:host port: withTimeout:- tag:];

    }else if([str isEqualToString:@"开始吧"]){

        NSLog(@"接收到数据:%@,host:%@",str,host);

        self.host = host;

        NSString *message = [NSString stringWithFormat:@"%@请求开始游戏!", host];

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"拒绝" otherButtonTitles:@"同意", nil];

        [alert show];

    }

    [self.socketUdp receiveWithTimeout:- tag:]; // 读取数据

    return YES;

}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{

    if (buttonIndex == ) { // 拒绝

        NSString *str = @"拒绝";

        [self.socketUdp sendData:[str dataUsingEncoding:NSUTF8StringEncoding] toHost:self.host port: withTimeout:- tag:];

    }else if(buttonIndex == ){ // 同意

        NSString *str = @"同意";

        [self.socketUdp sendData:[str dataUsingEncoding:NSUTF8StringEncoding] toHost:self.host port: withTimeout:- tag:];

    }

}

加入游戏代码:

- (void)viewDidLoad

{

    [super viewDidLoad];

    self.onlineGames = [NSMutableArray array];

    self.socketUdp = [[AsyncUdpSocket alloc] initWithDelegate:self];

    [self.socketUdp bindToPort: error:Nil];

    [self.socketUdp enableBroadcast:YES error:Nil];

    [self.socketUdp receiveWithTimeout:- tag:];

    // 发送数据

    NSString *str = @"有主机吗";

    [self.socketUdp sendData:[str dataUsingEncoding:NSUTF8StringEncoding] toHost:@"255.255.255.255" port: withTimeout:- tag:];

}

-(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{

    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    if ([str isEqualToString:@"有"]) {

        NSLog(@"str:%@, host:%@",str,host);

        if (![self.onlineGames containsObject:host]) { // 过滤掉重复的host

            [self.onlineGames addObject:host]; // 加入到数组中

        }

        [self.tableView reloadData];

    }else if ([str isEqualToString:@"拒绝"]){

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"对方拒绝了你的加入" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:Nil, nil];

        [alert show];

    }else if ([str isEqualToString:@"同意"]){

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"对方同意开始游戏" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:Nil, nil];

        [alert show];

    }

    [self.socketUdp receiveWithTimeout:- tag:];

    return YES;

}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    NSLog(@"%d",self.onlineGames.count);

    return self.onlineGames.count;

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    cell.textLabel.text = self.onlineGames[indexPath.row];

    return cell;

}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    NSString *host = self.onlineGames[indexPath.row]; // 获取到点击的host

    NSLog(@"发送数据:开始吧");

    [self.socketUdp sendData:[@"开始吧" dataUsingEncoding:NSUTF8StringEncoding] toHost:host port: withTimeout:- tag:]; // 发送数据

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"等待对方同意" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:Nil, nil];

    [alert show];

}

NSData比较耗内存,在不需要把文件加载进内存获取长度时使用NSHandle获取

高级UIKit-10(UDPSocket)的更多相关文章

  1. [Swift通天遁地]五、高级扩展-(10)整形、浮点、数组、字典、字符串、点、颜色、图像类的实用扩展

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  2. Oracle_高级功能(10) 备份恢复

    备份与恢复Oracle数据库有三种标准的备份方法,分别是导出/导入(EXP/IMP).热备份和冷备份.导出/导入是一种逻辑备份,冷备份和热备份是物理备份.一.导出/导入(Export/Import)利 ...

  3. Python的高级特性10:无聊的@property

    @property装饰器其实有点无聊,单独拿出来作为一个知识点其实没必要,尽管它可以将方法变成属性,让get和set方法更好用,但是,它破坏了python的简洁(不是代码的简洁而是指语法上). 下面来 ...

  4. UNIX环境高级编程--10. 信号

    第十章        信号    信号是软中断,提供了一种处理异步事件的方法.例如,终端用户键入终端键,会通过信号机制停止一个进程,或及早终止管道中的下一个程序.    每个信号都有一个名字,SIG开 ...

  5. Linux高级编程--10.Socket编程

    Linux下的Socket编程大体上包括Tcp Socket.Udp Socket即Raw Socket这三种,其中TCP和UDP方式的Socket编程用于编写应用层的socket程序,是我们用得比较 ...

  6. 【 D3.js 高级系列 — 10.0 】 思维导图

    思维导图的节点具有层级关系和隶属关系,很像枝叶从树干伸展开来的形状.在前面讲解布局的时候,提到有五个布局是由层级布局扩展来的,其中的树状图(tree layout)和集群图(cluster layou ...

  7. JavaScript高级程序设计10.pdf

    String类型有几种操作字符串的方法 concat()方法拼接任意多个字符串,不修改原字符串 var stringValue=“hello ”; var result=stringValue.con ...

  8. JavaScript高级程序设计-10.11: DOM及其扩展

    什么是DOM? DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API(应用程序编程接口).DOM描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分. 文档节点(do ...

  9. 第3节 mapreduce高级:10、11、分组求取topN

    只要修改OrderReducer.java的reduce方法,修改为: int i = 0;for(NullWritable nullWritable:values){ if(i>=2) bre ...

  10. KVM虚拟机高级设置——10 快照、克隆、替换磁盘

    查看虚拟机磁盘文件 [root@CentOS2 ~]# cd /var/lib/libvirt/images/ [root@CentOS2 images]# ll -h total 13G -rw-r ...

随机推荐

  1. CSS找到 (div+css请讲)

    CSS 定位和浮动 CSS 定位和浮动提供了一些特性,使用这些属性,你可以建立栏布局,的重叠布局的一部分,并有一些.也可多年来完成通常需要使用的多个表格能力完成的任务. 定位的基本思路是非常easy. ...

  2. rebol高速入门

    看了Java夜未眠之后,我也有点想学习其它语言了,希望能够完毕Python在写GUI程序和Web的程序的缺陷,写GUI程序比較看好VB,写Web程序看好PHP,不过首先想玩玩rebol. 翻译的Reb ...

  3. SharePoint 2010 BCS - 简单实例(一)数据源加入

    博客地址 http://blog.csdn.net/foxdave 本篇基于SharePoint 2010 Foundation. 我的数据库中有一个病人信息表Patient,如今我就想把这个表中的数 ...

  4. js中this的深入研究

    this对象是函数在运行时由调用函数的对象决定的: 1.在全局对象中运行函数时,this等于window 2.当函数被作为某个对象的方法调用时, this等于那个对象. 需要注意的几点: 声明函数里的 ...

  5. table中的换行问题

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  6. 一維條碼編碼規則(1D Barcode)

    1.Code 39 條碼:又分 標準型Code 39 條碼(Standard Code 39):資料內容包含有0~9數字,A~Z英文字母,”+”,”-“,”*”,”/”,”%”,”$”,”.”以及sp ...

  7. VC++对象布局的奥秘:虚函数、多继承、虚拟继承

    哈哈,从M$ Visual C++ Team的Andy Rich那里又偷学到一招:VC8的隐含编译项/d1reportSingleClassLayout和/d1reportAllClassLayout ...

  8. boost::thread用法

    最近在做一个消息中间件里面涉及到多线程编程,由于跨平台的原因我采用了boost线程库.在创建线程时遇到了几种线程创建方式现总结如下: 首先看看boost::thread的构造函数吧,boost::th ...

  9. 依赖于设备的位图(DDB) ,CreateCompatibleBitmap用法

    DDB(Device-dependent bitmap)依赖于具体设备,这主要体现在以下两个方面: DDB的颜色模式必需与输出设备相一致.例如,如果当前的显示设备是256色模式,那么DDB必然也是25 ...

  10. poco vs Boost

    Wooce Yang收集整理 POCO的优点: 1) 比boost更好的线程库,特别是一个活动的方法的实现,并且还可设置线程的优先级. 2) 比 boost:asio更全面的网络库.但是boost:a ...