iOS實(shí)現(xiàn)WIFI傳書

  • 問題

    業(yè)務(wù)場景上存在需要將手機(jī)里的文件粗俱、圖片傳遞給其他的設(shè)備旧烧,

    不僅僅局限于傳書、資料啥的都有可能傳遞

  • 方案

    最base的方法:設(shè)備之間加個(gè)云患民,設(shè)備上傳資料到云,云同步資料到各個(gè)設(shè)備垦梆,適用于多設(shè)備之間匹颤,這個(gè)沒講的必要

    如果是兩設(shè)備之間,忽略服務(wù)器托猩,怎么搞印蓖?聯(lián)想到圖書App中的WiFi傳書,貌似沒云端概念的京腥,怎么做到的赦肃?

  • 上菜

    • 采用框架GCDWebServer,通過CocoaPods引入
    pod "GCDWebServer", "~> 3.0"
    
    • 設(shè)置本地接收目錄公浪,初始化Server并啟動(dòng)
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        if let filepath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first as NSString? {
            let path = filepath.appendingPathComponent("transfer")
            if !FileManager.default.fileExists(atPath: path) {
                do {
                    try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: false, attributes: nil)
                } catch {
                    print(error)
                }
            }
            
            webServer = GCDWebUploader(uploadDirectory: path)
            webServer?.delegate = self
            webServer?.allowHiddenItems = true
            webServer?.allowedFileExtensions = ["doc", "docx", "xls", "xlsx", "txt", "pdf", "jpeg", "jpg"]
            webServer?.title = "善齋工具"
            webServer?.prologue = "歡飲使用善齋工具的WIFI管理平臺(tái)"
            webServer?.epilogue = "善齋書屋制作"
            
            if webServer?.start() == true, let address = IPHelper.deviceIPAdress(), address.count > 0, let port = webServer?.port {
                ipLb.text = "1.確保設(shè)備在同一局域網(wǎng) \n2.上傳時(shí)勿關(guān)閉該頁面 \n3.請(qǐng)網(wǎng)頁中輸入該地址 \nhttp://\(address):\(port)/"
            } else {
                ipLb.text = "GCDWebServer not running!"
            }
        }
    }
    
    • 局域網(wǎng)內(nèi)獲取本機(jī)的ip地址他宛,并設(shè)置其他設(shè)備訪問鏈接
    #import <ifaddrs.h>
    #import <arpa/inet.h>
    #import <net/if.h>
    
    @implementation IPHelper
    
    + (NSString *)deviceIPAdress {
        NSString *address = @"";
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
        int success = 0;
        success = getifaddrs(&interfaces);
        if (success == 0) { // 0 表示獲取成功
            temp_addr = interfaces;
            while (temp_addr != NULL) {
                if( temp_addr->ifa_addr->sa_family == AF_INET) {
                    // Check if interface is en0 which is the wifi connection on the iPhone
                    if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                        // Get NSString from C String
                        address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                    }
                }
                temp_addr = temp_addr->ifa_next;
            }
        }
        freeifaddrs(interfaces);
        return address;
        
    }
    
    
    #define IOS_CELLULAR    @"pdp_ip0"
    #define IOS_WIFI        @"en0"
    #define IOS_VPN         @"utun0"
    #define IP_ADDR_IPv4    @"ipv4"
    #define IP_ADDR_IPv6    @"ipv6"
    
    #pragma mark - 獲取設(shè)備當(dāng)前網(wǎng)絡(luò)IP地址
    + (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];
             //篩選出IP地址格式
             if([self isValidatIP:address]) *stop = YES;
         } ];
        return address ? address : @"0.0.0.0";
    }
    
    + (BOOL)isValidatIP:(NSString *)ipAddress {
        if (ipAddress.length == 0) {
            return NO;
        }
        NSString *urlRegEx = @"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
        
        NSError *error;
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlRegEx options:0 error:&error];
        
        if (regex != nil) {
            NSTextCheckingResult *firstMatch=[regex firstMatchInString:ipAddress options:0 range:NSMakeRange(0, [ipAddress length])];
            
            if (firstMatch) {
                NSRange resultRange = [firstMatch rangeAtIndex:0];
                NSString *result=[ipAddress substringWithRange:resultRange];
                //輸出結(jié)果
                NSLog(@"%@",result);
                return YES;
            }
        }
        return NO;
    }
    
    + (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;
    }
    
    
    • 在其他設(shè)備中訪問該地址即可
    let address = IPHelper.deviceIPAdress()
    let port = webServer?.port
    http://\(address):\(port)/
    
    • 備注:
      • 確保設(shè)備在同一局域網(wǎng)
      • 上傳時(shí)勿關(guān)閉該頁面
  • Game Over

    局域網(wǎng)中,設(shè)備作為server欠气,其他設(shè)備作為client堕汞,簡單的HTTP方式上傳文件到server,初始配置的路徑即為server接收后存放文件的路徑

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晃琳,一起剝皮案震驚了整個(gè)濱河市讯检,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卫旱,老刑警劉巖人灼,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異顾翼,居然都是意外死亡投放,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門适贸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來灸芳,“玉大人,你說我怎么就攤上這事拜姿±友” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵蕊肥,是天一觀的道長谒获。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么批狱? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任裸准,我火速辦了婚禮,結(jié)果婚禮上赔硫,老公的妹妹穿的比我還像新娘炒俱。我一直安慰自己,他們只是感情好爪膊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布权悟。 她就那樣靜靜地躺著,像睡著了一般惊完。 火紅的嫁衣襯著肌膚如雪僵芹。 梳的紋絲不亂的頭發(fā)上处硬,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天小槐,我揣著相機(jī)與錄音,去河邊找鬼荷辕。 笑死凿跳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疮方。 我是一名探鬼主播控嗜,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼骡显!你這毒婦竟也來了疆栏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤惫谤,失蹤者是張志新(化名)和其女友劉穎壁顶,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溜歪,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡若专,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蝴猪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片调衰。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖自阱,靈堂內(nèi)的尸體忽然破棺而出嚎莉,到底是詐尸還是另有隱情,我是刑警寧澤沛豌,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布萝喘,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏阁簸。R本人自食惡果不足惜爬早,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望启妹。 院中可真熱鬧筛严,春花似錦、人聲如沸饶米。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽檬输。三九已至照瘾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丧慈,已是汗流浹背析命。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逃默,地道東北人鹃愤。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像完域,于是被迫代替她去往敵國和親软吐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容