zoukankan      html  css  js  c++  java
  • 高级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:8000 error:Nil]; // 2.绑定端口
    
        [self.socketUdp enableBroadcast:YES error:Nil];// 3.开启广播
    
        [self.socketUdp receiveWithTimeout:-1 tag:0]; // 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:8000 error:Nil]; // 2.绑定端口
    
        [self.socketUdp enableBroadcast:YES error:Nil];// 3.开启广播
    
        [self.socketUdp receiveWithTimeout:-1 tag:0]; // 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:8000 withTimeout:-1 tag:0];
    
    }
    
    -(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:@"%@说:%@
    ",host,str]; // 其他人说的话
    
           
    
        }
    
        if ([str isEqualToString:@"谁在线"]) {
    
            NSString *str = @"我在线";
    
            NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    
            [self.socketUdp sendData:data toHost:host port:8000 withTimeout:-1 tag:0];
    
        }
    
        if ([str isEqualToString:@"我在线"]) {
    
            if (![self.hosts containsObject:host]) {
    
                [self.hosts addObject:host];
    
                [self.tableView reloadData];
    
            }
    
            
    
        }
    
        [self.socketUdp receiveWithTimeout:-1 tag:0]; // 接收数据
    
        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:10];
    
        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:8000 withTimeout:-1 tag:0];
    
            self.textView.text = [self.textView.text stringByAppendingFormat:@"我对所有人说:%@
    ",str];
    
        }else{
    
            // 私聊
    
            NSString *str = self.texiField.text;
    
            NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    
            // 发送数据
    
            [self.socketUdp sendData:data toHost:self.hostStr port:8000 withTimeout:-1 tag:0];
    
            self.textView.text = [self.textView.text stringByAppendingFormat:@"我对%@说:%@
    ",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:8000 error:Nil]; // 绑定端口
    
        [self.socketUdp enableBroadcast:YES error:Nil]; // 开启广播
    
        [self.socketUdp receiveWithTimeout:-1 tag:0]; // 读取数据
    
    }
    
    // 读取数据
    
    -(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:8000 withTimeout:-1 tag:0];
    
        }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:-1 tag:0]; // 读取数据
    
        return YES;
    
    }
    
    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    
        if (buttonIndex == 0) { // 拒绝
    
            NSString *str = @"拒绝";
    
            [self.socketUdp sendData:[str dataUsingEncoding:NSUTF8StringEncoding] toHost:self.host port:8000 withTimeout:-1 tag:0];
    
        }else if(buttonIndex == 1){ // 同意
    
            NSString *str = @"同意";
    
            [self.socketUdp sendData:[str dataUsingEncoding:NSUTF8StringEncoding] toHost:self.host port:8000 withTimeout:-1 tag:0];
    
        }
    
       
    
    }

     

    加入游戏代码:

    - (void)viewDidLoad
    
    {
    
        [super viewDidLoad];
    
        self.onlineGames = [NSMutableArray array];
    
        self.socketUdp = [[AsyncUdpSocket alloc] initWithDelegate:self];
    
        [self.socketUdp bindToPort:8000 error:Nil];
    
        [self.socketUdp enableBroadcast:YES error:Nil];
    
        [self.socketUdp receiveWithTimeout:-1 tag:0];
    
        // 发送数据
    
        NSString *str = @"有主机吗";
    
        [self.socketUdp sendData:[str dataUsingEncoding:NSUTF8StringEncoding] toHost:@"255.255.255.255" port:8000 withTimeout:-1 tag:0];
    
    }
    
     
    
    -(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:-1 tag:0];
    
        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:8000 withTimeout:-1 tag:0]; // 发送数据
    
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"等待对方同意" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:Nil, nil];
    
        [alert show];
    
    }

     

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

  • 相关阅读:
    GIL锁、进程池和线程池、同步和异步
    线程
    socket编程
    单例模式
    反射、自定义内置方法来定制类的功能、元类
    elasticSearch(一)--数据1
    docker学习整理(三)
    docker学习整理(二)
    docker学习整理(一)
    IDEA 配置mybatis生成代码
  • 原文地址:https://www.cnblogs.com/yangmx/p/3561312.html
Copyright © 2011-2022 走看看