高级UIKit-10(UDPSocket)
【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)的更多相关文章
- [Swift通天遁地]五、高级扩展-(10)整形、浮点、数组、字典、字符串、点、颜色、图像类的实用扩展
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Oracle_高级功能(10) 备份恢复
备份与恢复Oracle数据库有三种标准的备份方法,分别是导出/导入(EXP/IMP).热备份和冷备份.导出/导入是一种逻辑备份,冷备份和热备份是物理备份.一.导出/导入(Export/Import)利 ...
- Python的高级特性10:无聊的@property
@property装饰器其实有点无聊,单独拿出来作为一个知识点其实没必要,尽管它可以将方法变成属性,让get和set方法更好用,但是,它破坏了python的简洁(不是代码的简洁而是指语法上). 下面来 ...
- UNIX环境高级编程--10. 信号
第十章 信号 信号是软中断,提供了一种处理异步事件的方法.例如,终端用户键入终端键,会通过信号机制停止一个进程,或及早终止管道中的下一个程序. 每个信号都有一个名字,SIG开 ...
- Linux高级编程--10.Socket编程
Linux下的Socket编程大体上包括Tcp Socket.Udp Socket即Raw Socket这三种,其中TCP和UDP方式的Socket编程用于编写应用层的socket程序,是我们用得比较 ...
- 【 D3.js 高级系列 — 10.0 】 思维导图
思维导图的节点具有层级关系和隶属关系,很像枝叶从树干伸展开来的形状.在前面讲解布局的时候,提到有五个布局是由层级布局扩展来的,其中的树状图(tree layout)和集群图(cluster layou ...
- JavaScript高级程序设计10.pdf
String类型有几种操作字符串的方法 concat()方法拼接任意多个字符串,不修改原字符串 var stringValue=“hello ”; var result=stringValue.con ...
- JavaScript高级程序设计-10.11: DOM及其扩展
什么是DOM? DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API(应用程序编程接口).DOM描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分. 文档节点(do ...
- 第3节 mapreduce高级:10、11、分组求取topN
只要修改OrderReducer.java的reduce方法,修改为: int i = 0;for(NullWritable nullWritable:values){ if(i>=2) bre ...
- KVM虚拟机高级设置——10 快照、克隆、替换磁盘
查看虚拟机磁盘文件 [root@CentOS2 ~]# cd /var/lib/libvirt/images/ [root@CentOS2 images]# ll -h total 13G -rw-r ...
随机推荐
- Session、SessionId和Cookie的关系
Session是保存在服务器中的,SessionId是保存在Cookie中的. 当用户·登录时候,系统会将"用户名"和"密码"保存到Session中,系统会给每 ...
- Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器
Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器 MVC概念 MVC的含义是 “模型-视图-控制器”.MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程 ...
- 由命名空间函数而引发思考--js中的对象赋值问题
最近没有编码任务,作为一个才毕业的小辣鸡,给的任务就是看一下公司的新系统,熟悉怎么用哪些地方是干什么的. 下午喝了两杯水,感觉有点浪.然后就开始看了下代码.发现有一个函数是这样子的. var TX = ...
- js 精美倒计时
精美倒计时*{ padding:0; margin:0;}.colockbox{width:250px;height:30px;background:url(/jscss/demoimg/201312 ...
- OC中属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
此次只做简单说明,不做代码演示! 1> readwrite:同时生成get方法和set方法的声明和实现 2> readonly:只生成get方法的声明和实现 3> assign:se ...
- Python网络编程——通过指定的端口和协议找到服务名
1.通过指定的端口和协议找到对应的服务名,采用socket中getservbyprot()函数实现. import socket def find_service_name(): protocolna ...
- Spark1.5.1的安装与部署 每一步详细测试截图
转载或借鉴请注明转自 http://www.cnblogs.com/FG123/p/5101733.html 谢谢! 1.安装Spark之前需要先安装Java,Scala及Python(个人喜欢用p ...
- C语言循环小技巧
写代码,有两类追求,一种是追求实用(Coder),一种是追求代码艺术(Artist) 我是那种追实用追腻了,偶然追一下艺术(就是偶然和艺术有一腿)的那种Coder 很多人,已经习惯了for(i=0; ...
- Apache中RewriteCond规则参数介绍(转)
CodeIgniter2.0已经出来有20多天了呢~也就是我一直用的php框架(CI).一直都在研究jquery,倒是把CI给忘到一边去了,呵呵~~今天公司事情不是很多,于是开始熟悉一下CI2.0的一 ...
- UVA 270 Lining Up 共线点 暴力
题意:给出几个点的位置,问一条直线最多能连过几个点. 只要枚举每两个点组成的直线,然后找直线上的点数,更新最大值即可. 我这样做过于暴力,2.7s让人心惊肉跳...应该还能继续剪枝的,同一直线找过之后 ...