关于wifi通信

2017-04-17  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读