iOS udp socket通信-远程唤醒windows电脑主机

一、原理说明

1、远程开机Wake onLAN(WOL)简介:
俗称远程唤醒,是现在很多网卡都支持的功能。而远程唤醒的实现,主要是向目标主机发送特殊格式的数据包,是AMD公司制作的MagicPacket这套软件以生成网络唤醒所需要的特殊数据包,俗称魔术包(Magic Packet)。MagicPacket格式虽然只是AMD公司开发推广的技术,并非世界公认的标准,但是仍然受到很多网卡制造商的支持,因此许多具有网络唤醒功能的网卡都能与之兼容。原理上我们不用深入,实现上是发一个BroadCast包,包的内容包括以下数据就可以了。FF FF FF FF FF FF,6个FF是数据的开始,紧跟着16次MAC地址就可以了。我们采用<a href="http://baike.baidu.com/link?url=S-2pRxOGTT6z4-Ibl4rY2y4uxXlVw6Y9ilkgSjQTkZYsbXAw4dk5ARXQFAVlFI__dt-NI6mcdcpyUsQ1pMs1mq">UDP协议</a>发送广播包的形式来实现对电脑主机的唤醒
2、设置pc-B 首先需要进行BIOS和网卡设置,启动计算机,进入BIOS参数设置。选择电源管理设置“Power Management Setup”选项,将“Wake up on LAN”项和“Wake on PCI Card”项均设置为“Enable”,启用该计算机的远程唤醒功能。 (各个主板不一样,可以在百度上搜索怎么开启你家电脑的主板的远程唤醒功能)
3、获取pc-B的<a href="http://baike.baidu.com/link?url=vSrHHlYjyTWDmS_RWuUIz0fNNt2ro8SbM_OCVkj0mGy-3-JIqDnYdCzeMNfvigUuBAcnion-VpVGB_1ZXbxUQa">Mac地址</a> 通过命令行输入ipconfig/all可以得到pc-B的地址 00 0B 2F 70 40 9E

二、代码实现

我们需要用到一个socket的三方AsyncSocket,这个三方比较老了,还是非ARC的代码,因为感觉用起来还可以,所以就一直在使用。
https://github.com/roustem/AsyncSocket
下载此三方,导入到项目中
备注:由于是非ARC模式的三方,我的项目是ARC模式,所以需要手动改成支持ARC模式

arc模式.png

1、新建一个类 继承NSObject即可 我们命名为"SocketConnect"

导入AsyncSocket 的

#import <Foundation/Foundation.h>
#import "AsyncUdpSocket.h"

定义SocketConnect.h的属性和方法

//ip地址
@property (strong,nonatomic)NSString *hostIpAddress;
//端口号
@property (assign,nonatomic)NSInteger hostPort;
//udp Socket
@property (strong,nonatomic)AsyncUdpSocket *udpSocket;

/**
 *  唤醒状态的回调
 */
@property (strong,nonatomic)void(^wakeState)(BOOL result);

//socket单例
+ (instancetype)sharedInstance;

/**
 *  远程唤醒电脑
 *
 *  @param sendData data数据
 *  @param result   返回唤醒的状态
 */
- (void)wakeUp:(NSData *)sendData result:(void(^)(BOOL result))result;

在SocketConnect.m实现方法

#pragma mark - 懒加载

- (AsyncUdpSocket *)udpSocket{
    
    if (!_udpSocket) {
        
        _udpSocket = [[AsyncUdpSocket alloc]initWithDelegate:self];
        NSError *error = nil;
        //开启广播模式
        [_udpSocket enableBroadcast:YES error:&error];
        NSLog(@"%@",error);
    }
    return _udpSocket;
}

//懒加载结束

#pragma mark - 初始化单例对象
+ (instancetype)sharedInstance{
    
    static SocketConnect *socketConnect = nil;
    static dispatch_once_t oneToken;
    
    dispatch_once(&oneToken, ^{
        
        socketConnect = [[SocketConnect alloc]init];
        
    });
    return socketConnect;
}

- (void)wakeUp:(NSData *)sendData result:(void (^)(BOOL))result{

    self.wakeState = result;
    //由于是局域网,我直接发送洪的广播包,如果做远程唤醒,需要替换这里的ip地址
    [self.udpSocket sendData:sendData toHost:@"255.255.255.255" port:self.hostPort withTimeout:-1 tag:0];

}

#pragma mark - socket协议方法

//已接收到消息
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{
    
    
    return YES;

}
//没有接受到消息
-(void)onUdpSocket:(AsyncUdpSocket *)sock didNotReceiveDataWithTag:(long)tag dueToError:(NSError *)error{
    
    
    
    
}
//没有发送出消息
-(void)onUdpSocket:(AsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error{
    
    self.wakeState(NO);
    
    
}
//已发送出消息
-(void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag{
    
    
    self.wakeState(YES);
    
    
}
//断开连接
-(void)onUdpSocketDidClose:(AsyncUdpSocket *)sock{
    
    
    
    
}

2、使用方法

我们在demo 中默认的ViewController.m文件中viewDidLoad,添加一个UITextField和button来模仿下udp通信,我习惯用<a href ="https://github.com/SnapKit/Masonry">Masonry</a>来实现页面的布局,如果你对此不是很了解,可以使用拖控件来实现,界面很简单,笔者就不细说了

@interface ViewController (){

    UITextField *inputTextField;
    UIButton *sendBtn;

}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    inputTextField = [[UITextField alloc]init];
    inputTextField.placeholder = @"发一个";
    inputTextField.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:inputTextField];
    
    sendBtn = [UIButton buttonWithType:UIButtonTypeSystem];
    [sendBtn setTitle:@"发送" forState:UIControlStateNormal];
    [sendBtn addTarget:self action:@selector(sendMessage) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:sendBtn];
    
    
    [inputTextField mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.center.equalTo(self.view);
        make.height.equalTo(@30);
        make.left.equalTo(@20);
        make.right.equalTo(self.view.mas_right).with.offset(-20);
    }];
    
    [sendBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.top.equalTo(inputTextField.mas_bottom);
        make.centerX.equalTo(inputTextField.mas_centerX);
        make.width.height.equalTo(@50);
    }];
    
}

- (void)sendMessage{
    NSData *data = [inputTextField.text dataUsingEncoding:NSUTF8StringEncoding];

    SocketConnect *socket = [SocketConnect sharedInstance];
   //设置端口号为8888
    socket.hostPort = 8888;
    if (inputTextField.text.length != 0 ) {

        [socket wakeUp:data result:^(BOOL result) {
            //消息是否发送成功的回调
            NSLog(@"%d",result);
            
            
        }];
        
    }
    
    

}

UDP通信的基本代码写完了,在运行之前,我们下找一个小工具来测试下吧,笔者用到的工具SocketTool 是一个TCP/IP测试工具,我已经上传到百度云,读者可放心下载
http://pan.baidu.com/s/1pKpSyj5

SocketTool使用方法.gif

显示可以运行我们的项目了,来看下运行的效果


运行效果.gif

如果你运行出来也是这样子的效果,说明你的UDP通信就没问题了,下面我们来实现电脑主机的网络唤醒,我们只需要在sendMessage里面的方法做下修改即可,大概思路就是拼接魔术包

- (void)sendMessage{
    //被控制的电脑主机的mac地址
    Byte mac[6] = {0x60,0xf8,0x1d,0xad,0x3a,0xf0};
    Byte packet[17 * 6] = {};
    for (int i = 0 ; i < 6; i++)
        packet[i] = 0xFF;
    for (int i = 1; i <= 16; i++) {
        
        for (int j = 0; j < 6; j++) {
            
            packet[i * 6 + j] = mac[j];
            
        }
        
    }

    SocketConnect *socket = [SocketConnect sharedInstance];
    socket.hostPort = 8888;
    
    NSData *data = [NSData dataWithBytes:packet length:sizeof(packet)];
    [socket wakeUp:data result:^(BOOL result) {
        
        NSLog(@"%d",result);
        
        
    }];
    


}

OK,全部搞定,运行项目就可以唤醒被控制的电脑的开机了,如果需要做远程唤醒,则需要在路由器上做下端口映射,并把以下位置修改为你的ip地址或者域名地址即可

   [self.udpSocket sendData:sendData toHost:@"IP地址" port:self.hostPort withTimeout:-1 tag:0];

了解更多请访问iOS udp socket通信-远程唤醒windows电脑主机!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者...
    保川阅读 5,939评论 1 13
  • 个人认为,Goodboy1881先生的TCP /IP 协议详解学习博客系列博客是一部非常精彩的学习笔记,这虽然只是...
    贰零壹柒_fc10阅读 5,048评论 0 8
  • 1.这篇文章不是本人原创的,只是个人为了对这部分知识做一个整理和系统的输出而编辑成的,在此郑重地向本文所引用文章的...
    SOMCENT阅读 13,031评论 6 174
  • WakeOnLan 首先简单介绍一下什么是WakeOnLanWake-On-LAN简称WOL,是一种电源管理功能;...
    爱捣腾的吴大爷阅读 75,054评论 9 32
  • 总有一条蜿蜒在童话镇里七彩的河,沾染魔法的乖张……,最近迷上了很多不同类型的歌,童话镇啦,卡百利的dying i...
    八零八七阅读 170评论 0 0