美文网首页
关于wifi通信

关于wifi通信

作者: 未知的远方 | 来源:发表于2017-04-17 21:06 被阅读62次

    由于项目需要,需要和安卓在没网的情况下传递数据,所以研究了一下“wifi通信”和“蓝牙”
    1,蓝牙(随便说一下)
    首先声明,蓝牙这条书走不通,下面是我的尝试
    安卓机可以搜索到苹果的蓝牙,但是苹果手机无法搜索到安卓机的蓝牙(苹果4s是可以搜索到的),链接苹果机开启配对,也可以配对成功,但是 配对密码是无用的,苹果机是直接就连上了,之后ios程序里 关于蓝牙的回调和各种代理方法失效,好像只是蓝牙连上了,没有后续!蓝牙宣告结束
    2,wifi链接
    特别注意:与安卓互联的时候需要在发送的字符串后面加上"\r\n",这是一个传输协议
    下面是几个参考的链接,目前只能传数字和字母(汉字会失败)
    @http://qk13warcraft.blog.163.com/blog/static/1575493442012778524173/
    下面这个是用到的第三方库的地址
    @https://git.oschina.net/zdsoft/AsyncSocket-SeverDemoAndClientDemo
    1,下载第三方库到本地 找到 并拉入项目中

    1

    2,拉入四个官方的库

    2

    3,把这个文件改成MRC(在后面加上-fno-objc-arc)

    3

    4,至此,准备工作做完了,开始加入代码(服务器端)

    引入头文件
    #import "AsyncSocket.h"
    宏定义
    #define WELCOME_MSG  0
    #define ECHO_MSG     1
    #define WARNING_MSG  2
    
    #define READ_TIMEOUT 5.0
    #define READ_TIMEOUT_EXTENSION 10.0
    声明变量
    @implementation ViewController{
        AsyncSocket *listenSocket;
        NSMutableArray *connectedSockets;
        
        BOOL isRunning;
        
        UITextField *tfSender;
        UIButton *btnSend;
        
        
    
        UIButton *btnPort;
    }
    //初始化AsyncSocket
    - (void)initAsyncSocket{
        listenSocket = [[AsyncSocket alloc] initWithDelegate:self];
        connectedSockets = [[NSMutableArray alloc] initWithCapacity:1];
        isRunning = NO;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self initAsyncSocket];
        NSLog(@"Ready");
        
        // Advanced options - enable the socket to contine operations even during modal dialogs, and menu browsing
        NSArray *arr = [NSArray arrayWithObject:NSRunLoopCommonModes];
        NSLog(@"%@",arr);
        [listenSocket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
        [listenSocket readDataWithTimeout:-1 tag:0];
    
        
        
        //    设置要连接的port
        btnPort = [[UIButton alloc]initWithFrame:CGRectMake(10, 150, 100, 30)];
        [self.view addSubview:btnPort];
        [btnPort addTarget:self action:@selector(setstart:) forControlEvents:UIControlEventTouchUpInside];
        [btnPort setBackgroundColor:[UIColor orangeColor]];
        [btnPort setTitle:@"开始" forState:UIControlStateNormal];
        
        tfSender = [[UITextField alloc]initWithFrame:CGRectMake(10, 200, 200, 30)];
        [self.view addSubview:tfSender];
        [tfSender setPlaceholder:@"请输入发送内容"];
        [tfSender setBackgroundColor:[UIColor yellowColor]];
        [tfSender setKeyboardType:UIKeyboardTypeNumberPad];
        
        btnSend = [[UIButton alloc]initWithFrame:CGRectMake(220, 200, 60, 30)];
        [self.view addSubview:btnSend];
        [btnSend addTarget:self action:@selector(sendMessage) forControlEvents:UIControlEventTouchUpInside];
        [btnSend setBackgroundColor:[UIColor orangeColor]];
        [btnSend setTitle:@"发送" forState:UIControlStateNormal];
        
    }
    
    - (void)sendMessage{
        [tfSender resignFirstResponder];
        
        NSString *str = tfSender.text;
        NSLog(@"发送的内容:%@",str);
        NSData *data=[str dataUsingEncoding:NSUTF8StringEncoding];
        [listenSocket writeData:data withTimeout:-1 tag:1];
    }
    
    //开始 设置port
    - (void)setstart:(id)sender {
        
        [listenSocket readDataWithTimeout:-1 tag:0];
        
        if(!isRunning)
        {
            
            int port = 8080;
            
            if(port < 0 || port > 65535)
            {
                port = 0;
            }
            
            NSError *error = nil;
            if(![listenSocket acceptOnPort:port error:&error])
            {
                
                return;
            }
            
            
            isRunning = YES;
            [btnPort setTitle:@"停止" forState:UIControlStateNormal];
            
        }
        else
        {
            // Stop accepting connections
            [listenSocket disconnect];
            
            // Stop any client connections
            int i;
            for(i = 0; i < [connectedSockets count]; i++)
            {
                // Call disconnect on the socket,
                // which will invoke the onSocketDidDisconnect: method,
                // which will remove the socket from the list.
                [[connectedSockets objectAtIndex:i] disconnect];
            }
            
            
            isRunning = false;
            [btnPort setTitle:@"开始" forState:UIControlStateNormal];
        }
        
    }
    
    //下面是代理方法
    - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
    {
        [connectedSockets addObject:newSocket];
    }
    
    - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
    {
        //  [self logInfo:FORMAT(@"Accepted client %@:%hu", host, port)];
        
        NSString *welcomeMsg = @"连接到服务器了\r\n";
        NSData *welcomeData = [welcomeMsg dataUsingEncoding:NSUTF8StringEncoding];
        
        [sock writeData:welcomeData withTimeout:-1 tag:WELCOME_MSG];
        
        [sock readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:0];
    }
    
    - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
    {
        if(tag == ECHO_MSG)
        {
            [sock readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:0];
        }
    }
    
    - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length] - 2)];
        NSString *msg = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
        if(msg)
        {
            NSString *str=[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"客户端发送来的是:%@",str);
            
            str =[str stringByAppendingString:@"这是服务器回的"];
            NSData *data=[str dataUsingEncoding:NSUTF8StringEncoding];
            [sock writeData:data withTimeout:-1 tag:1];
            listenSocket = sock;
        }
        else
        {
            //      [self logError:@"Error converting received data into UTF-8 String"];
        }
        
        // Even if we were unable to write the incoming data to the log,
        // we're still going to echo it back to the client.
        //  [sock writeData:data withTimeout:-1 tag:ECHO_MSG];
    }
    
    /**
     * This method is called if a read has timed out.
     * It allows us to optionally extend the timeout.
     * We use this method to issue a warning to the user prior to disconnecting them.
     **/
    - (NSTimeInterval)onSocket:(AsyncSocket *)sock
      shouldTimeoutReadWithTag:(long)tag
                       elapsed:(NSTimeInterval)elapsed
                     bytesDone:(CFIndex)length
    {
        if(elapsed <= READ_TIMEOUT)
        {
            NSString *warningMsg = @"哈哈 我是服务器\r\n";
            NSData *warningData = [warningMsg dataUsingEncoding:NSUTF8StringEncoding];
            
            [sock writeData:warningData withTimeout:-1 tag:WARNING_MSG];
            
            return READ_TIMEOUT_EXTENSION;
        }
        
        return 0.0;
    }
    
    - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
    {
        NSLog(@"Client Disconnected: %@:%hu",[sock connectedHost],[sock connectedPort]);
    }
    
    - (void)onSocketDidDisconnect:(AsyncSocket *)sock
    {
        [connectedSockets removeObject:sock];
    }
    
    

    5,下面是客户端代码

    //引入头文件 宏定义
    
    #import "AsyncSocket.h"
    
    //首先导入头文件信息
    #include <ifaddrs.h>
    #include <arpa/inet.h>
    #include <net/if.h>
    
    #define IOS_CELLULAR    @"pdp_ip0"
    #define IOS_WIFI        @"en0"
    //#define IOS_VPN       @"utun0"
    #define IP_ADDR_IPv4    @"ipv4"
    #define IP_ADDR_IPv6    @"ipv6"
    
    @interface ViewController ()
    @property (retain,nonatomic)AsyncSocket *client;
    @end
    
    @implementation ViewController{
        
        
        UITextField *tfSend;
        UILabel *lblbackContent;
        
        NSString *ipStr;
        int portInt;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        UIButton *btnSure = [[UIButton alloc]initWithFrame:CGRectMake(10, 180, 160, 40)];
        [self.view addSubview:btnSure];
        [btnSure setBackgroundColor:[UIColor orangeColor]];
        [btnSure addTarget:self action:@selector(ClientToSever) forControlEvents:UIControlEventTouchUpInside];
        [btnSure setTitle:@"连接到服务器" forState:UIControlStateNormal];
        
    //    发送内容
        
        tfSend = [[UITextField alloc]initWithFrame:CGRectMake(10, 230, 200, 30)];
        [self.view addSubview:tfSend];
        [tfSend setBackgroundColor:[UIColor yellowColor]];
        [tfSend setPlaceholder:@"发送内容"];
        
        UIButton *btnSend = [[UIButton alloc]initWithFrame:CGRectMake(10, 270, 60, 40)];
        [self.view addSubview:btnSend];
        [btnSend setBackgroundColor:[UIColor orangeColor]];
        [btnSend addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside];
        [btnSend setTitle:@"发送" forState:UIControlStateNormal];
        
        
    //    服务器返回内容
        lblbackContent = [[UILabel alloc]initWithFrame:CGRectMake(10, 320, 340, 200)];
        [self.view addSubview:lblbackContent];
        lblbackContent.text = @"服务器返回的数据:";
        [lblbackContent setBackgroundColor:[UIColor yellowColor]];
        lblbackContent.numberOfLines = 10;
    }
    
    -(int)connectSever{
    //先获取本机链接的热点的ip
        ipStr  = [self getIPAddress:YES];
        
    //获取服务器端的ip
        ipStr = [ipStr substringToIndex:ipStr.length - 1];
        ipStr = [NSString stringWithFormat:@"%@1",ipStr];
        
        portInt = 8080;
        
        if (_client==nil) {
            _client =[[AsyncSocket alloc]initWithDelegate:self];
            NSError *error=nil;
            if (![_client connectToHost:ipStr onPort:portInt error:&error]) {
                NSLog(@" error --- %@  %@",error,[error localizedDescription]);
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Connection failed to host" message:@"error" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"YES", nil];
                [alert show];
                return 2;
            }
            //
            else{
                
                NSLog(@"连接成功");
                return 1;
            }
            
        }
        else{
            [_client readDataWithTimeout:-1 tag:0];
            return 0;
        }
    }
    
    //连接服务器
    - (void)ClientToSever {
        int state =[self connectSever];
        switch (state) {
            case 1:
                [self showMessage:@"连接成功"];
                break;
            case 2:
                [self showMessage:@"连接失败"];
                break;
            case 0:
                [self showMessage:@"不必再连,已连接"];
                break;
            default:
                break;
        }
    }
    
    //发送信息
    - (void)sendMessage:(id)sender {
        [tfSend resignFirstResponder];
        
        NSString *str = tfSend.text;
        NSString *content =[str stringByAppendingString:@"\r\n"];
        NSLog(@"str --->%@",content);
        NSData *data4=[content dataUsingEncoding:4];
        [_client writeData:data4 withTimeout:-1 tag:0];
    }
    
    - (void) showMessage:(NSString *) msg{
        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"Alert!"
                                                        message:msg
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    }
    
    #pragma mark -- Asy ---Soc Delegate
    -(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{
        [_client readDataWithTimeout:-1 tag:0];
        NSLog(@"Delegate...  连接上服务器了,监听中");
    }
    -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{
        NSLog(@"Delegate...发生错误:%@",err);
    }
    -(void)onSocketDidDisconnect:(AsyncSocket *)sock{
        NSString *msg=@"连接失败";
        [self showMessage:msg];
        _client=nil;
        NSLog(@"Delegate...连接失败");
        
    }
    -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
        NSString *str=[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        
        NSArray *arrbackc = [str componentsSeparatedByString:@"\r\n"];
        if (arrbackc.count == 2) {
            NSData *backData4 = [arrbackc[0] dataUsingEncoding:4];
            NSString *strContent4 = [[NSString alloc]initWithData:backData4 encoding:4];
            str = [NSString stringWithFormat:@"%@",strContent4];
        }
        
        NSLog(@"Delegate...接收到的数据是%@",str);
        lblbackContent.text=str;
        //    [str release];
        [_client readDataWithTimeout:-1 tag:0];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    - (NSString *)getIPAddress:(BOOL)preferIPv4
    {
        NSArray *searchArray = preferIPv4 ?
        @[ /*IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6,*/ IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
        @[ /*IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4,*/ IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
        
        NSDictionary *addresses = [self getIPAddresses];
        NSLog(@"addresses: %@", addresses);
        
        __block NSString *address;
        [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
         {
             address = addresses[key];
             if(address) *stop = YES;
         } ];
        return address ? address : @"0.0.0.0";
    }
    
    //获取所有相关IP信息
    - (NSDictionary *)getIPAddresses
    {
        NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
        
        // retrieve the current interfaces - returns 0 on success
        struct ifaddrs *interfaces;
        if(!getifaddrs(&interfaces)) {
            // Loop through linked list of interfaces
            struct ifaddrs *interface;
            for(interface=interfaces; interface; interface=interface->ifa_next) {
                if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
                    continue; // deeply nested code harder to read
                }
                const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
                char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
                if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
                    NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
                    NSString *type;
                    if(addr->sin_family == AF_INET) {
                        if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
                            type = IP_ADDR_IPv4;
                        }
                    } else {
                        const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
                        if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
                            type = IP_ADDR_IPv6;
                        }
                    }
                    if(type) {
                        NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
                        addresses[key] = [NSString stringWithUTF8String:addrBuf];
                    }
                }
            }
            // Free memory
            freeifaddrs(interfaces);
        }
        return [addresses count] ? addresses : nil;
    }
    

    6,操作步骤,demo正常运行之后
    服务器端操作
    (1):作为服务器端的手机关闭wifi和蓝牙(不关闭的话,发出的热点,另外一个手机搜索不到)


    问题解释 1

    (2):

    2

    (3):


    3

    (4):

    4

    (5):

    5

    (6):

    6

    客户端操作:
    (1):

    client1 ![Uploading F6881C1BF10CDA6B5170616ACB0B8464_143209.png . . .]

    (2):

    client2

    (3):

    client3

    (4):

    client4

    (5):

    client5

    (6):

    client6

    相关文章

      网友评论

          本文标题:关于wifi通信

          本文链接:https://www.haomeiwen.com/subject/hxxtzttx.html