通过 wifi 传输数据

Posted

技术标签:

【中文标题】通过 wifi 传输数据【英文标题】:Data transfer over wifi 【发布时间】:2017-11-16 14:25:57 【问题描述】:

我在 android 设备上创建了一个热点/wifi-direct。并将这个 wifi 连接到 ios 设备。 现在我想创建一个 iOS 应用程序,它将能够通过 wifi 发送和接收数据。 如果可以,我该怎么做?

【问题讨论】:

是的,这是可能的(你可以考虑Xender 为例),但是这里解释太长了。您应该找到一些相同的教程! @Lion 你能放一些链接或答案吗?谢谢 您的一个设备必须是服务器,另一个是客户端。然后你可以定义他们交流的方式。 连接已建立。那么现在我们可以使用socket进行数据传输了吗? 连接已建立。据我了解,iOS 设备作为客户端工作,而 android 设备作为服务器工作现在在我的 iOS 应用程序中,我需要编写“数据接收器”来从服务器接收数据,并编写“数据发送器”来将数据发送到服务器。所以我正在寻找这个“接收器和发射器”示例代码 【参考方案1】:

是的,可以,你可以在安卓上运行本地服务器,我推荐https://github.com/NanoHttpd/nanohttpd 那么你必须在iOS设备上获取IP地址才能进行http请求,有c方法获取路由IP地址

#include "IpHelper.h" // my header file

#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <string.h>
#include <arpa/inet.h>

#if TARGET_IPHONE_SIMULATOR
#include <net/route.h>
#else
#include "route.h"
#endif

#define CTL_NET         4               /* network, see socket.h */

#if defined(BSD) || defined(__APPLE__)

#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))

int getdefaultgateway(in_addr_t * addr)

    int mib[] = CTL_NET, PF_ROUTE, 0, AF_INET,
        NET_RT_FLAGS, RTF_GATEWAY;
    size_t l;
    char * buf, * p;
    struct rt_msghdr * rt;
    struct sockaddr * sa;
    struct sockaddr * sa_tab[RTAX_MAX];
    int i;
    int r = -1;
    if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) 
        return -1;
    
    if(l>0) 
        buf = malloc(l);
        if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) 
            return -1;
        
        for(p=buf; p<buf+l; p+=rt->rtm_msglen) 
            rt = (struct rt_msghdr *)p;
            sa = (struct sockaddr *)(rt + 1);
            for(i=0; i<RTAX_MAX; i++) 
                if(rt->rtm_addrs & (1 << i)) 
                    sa_tab[i] = sa;
                    sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
                 else 
                    sa_tab[i] = NULL;
                
            

            if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
               && sa_tab[RTAX_DST]->sa_family == AF_INET
               && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) 


                if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) 
                    char ifName[128];
                    if_indextoname(rt->rtm_index,ifName);

                    if(strcmp("en0",ifName)==0)

                        *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
                        r = 0;
                    
                
            
        
        free(buf);
    
    return r;


#endif

你还需要从这里https://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/net/route.h从苹果开源下载并导入 route.h

最后你可以得到本地 http url http://+'ip you get before'+ :'port of server you lunched on android'

所以,现在您可以通过 ALamofire(或其他)向本地服务器发出 http 请求了。

编辑 1: 我在我的旧项目中发现了这段代码,你可以使用 CocoaAsyncSocket 进行数据传输,它是用 swift 3 编写的,我知道你想要一些在 objC 上编写的代码,但找不到这样的代码,如果我不能完全回答你的问题,抱歉.

import CocoaAsyncSocket
import UIKit

enum TAG: Int 
    case header = 1
    case body   = 2


class ViewController: UIViewController, NetServiceDelegate, NetServiceBrowserDelegate, GCDAsyncSocketDelegate 

    var service : NetService!
    var socket  : GCDAsyncSocket!
    var newSocket: GCDAsyncSocket!
    var serviceBrowser = NetServiceBrowser()
    var adresses: [Data]?

    override func viewDidLoad() 
        super.viewDidLoad()
        startTalking()
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
    

    func parseHeader(data: NSData) -> UInt 
        var out: UInt = 0
        data.getBytes(&out, length: MemoryLayout<UInt>.size)
        return out
    

    func handleResponseBody(data: NSData) 
        if let message = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue) 
            print(message)
        
    

    func sendText() 
        if let data = "aaaaa".data(using: String.Encoding.utf8) 
            var header = data.count
            let headerData = NSData(bytes: &header, length: MemoryLayout<UInt>.size)
            self.socket.write(headerData as Data, withTimeout: -1.0, tag: TAG.header.rawValue)
            self.socket.write(data, withTimeout: -1.0, tag: TAG.body.rawValue)
        
    

    func startTalking () 
        self.socket = GCDAsyncSocket(delegate: self, delegateQueue: DispatchQueue.main)
        self.socket.isIPv4PreferredOverIPv6 = false

        do 
            try self.socket.connect(toHost: "localhost", onPort: UInt16(8080), withTimeout: -1)
         catch let err 
            print(err)
        
    

    /*
     *  Delegates of NSNetService
     **/


    func netServiceBrowser(_ browser: NetServiceBrowser, didFindDomain domainString: String, moreComing: Bool) 
        print(111)
    


    func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) 
        print("aaaaaaa")
    

    func netServiceDidPublish(_ sender: NetService) 
        print("Bonjour service published. domain: \(sender.domain), type: \(sender.type), name: \(sender.name), port: \(sender.port)")
    

    func netService(_ sender: NetService, didNotPublish errorDict: [String : NSNumber]) 
        print("Unable to create socket. domain: \(sender.domain), type: \(sender.type), name: \(sender.name), port: \(sender.port), Error \(errorDict)")
    

    func netService(_ sender: NetService, didAcceptConnectionWith inputStream: InputStream, outputStream: OutputStream) 
        print("4")
    

    /*
     *  END OF Delegates
     **/

    /*
     *  Delegates of GCDAsyncSokcket
     **/

    func socketDidSecure(_ sock: GCDAsyncSocket) 
        print("3")
    

    func socket(_ sock: GCDAsyncSocket, didConnectToHost host: String, port: UInt16) 
        print("connected")
        self.socket.readData(toLength: UInt(MemoryLayout<UInt64>.size), withTimeout: -1, tag: 0)
    

    func socket(_ sock: GCDAsyncSocket, didAcceptNewSocket newSocket: GCDAsyncSocket) 
        print("Did accept new socket")
        self.newSocket = newSocket

        self.newSocket.readData(toLength: UInt(MemoryLayout<UInt64>.size), withTimeout: -1.0, tag: 0)
        print("Connected to " + self.service.name)
    

    func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) 
        print("Socket disconnected: error \(err)")
        if self.socket == socket 
            //            print("Disconnected from " + self.service.name)
        
    

    func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int) 
        if data.count == MemoryLayout<UInt>.size 
            let bodyLength: UInt = self.parseHeader(data: data as NSData)
            sock.readData(toLength: bodyLength, withTimeout: -1, tag: TAG.body.rawValue)
         else 
            self.handleResponseBody(data: data as NSData)
            sock.readData(toLength: UInt(MemoryLayout<UInt>.size), withTimeout: -1, tag: TAG.header.rawValue)
        
    

    func socket(_ sock: GCDAsyncSocket, didWriteDataWithTag tag: Int) 
        print("Write data with tag of \(tag)")
    

    func socket(_ sock: GCDAsyncSocket, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) 
        completionHandler(true)
    

    /*
     *  END OF Delegates
     **/

编辑 2: 在这里将 ip 解析为人类可读的字符串是 Objc 方法

+ (NSString *)getGatewayIP 
    NSString *ipString = nil;
    struct in_addr gatewayaddr;
    int r = getdefaultgateway(&(gatewayaddr.s_addr));
    if(r >= 0) 
        ipString = [NSString stringWithFormat: @"%s",inet_ntoa(gatewayaddr)];
        NSLog(@"default gateway : %@", ipString );
     else 
        NSLog(@"getdefaultgateway() failed");
    

    return ipString;

【讨论】:

谁能提供iOS(Objective-C)中TCP socket-client的示例代码? 我使用“IpHelper.h”来获取路由器的IP,但它没有给出正确的IP。它返回“29825196”但IP是“172.24.199.1” 我通过使用“ NSLog(@"%@",[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr)])得到了正确的IP 您必须将其解析为人类可读的字符串,对不起,这是我的失败,我将在几分钟内使用该代码编辑答案

以上是关于通过 wifi 传输数据的主要内容,如果未能解决你的问题,请参考以下文章

STM32单片机通过ESP8266WiFi模块与Android APP实现数据传输---上位机搭建

在iOS上通过WiFi和蓝牙流式传输视频

通过 WiFi 在 Android 手机之间流式传输语音

4G模块,wifi模块是啥,工作原理是啥

通过 Wifi Direct 传输文件

Android基于WIFI实现电脑和手机间数据传输的技术方案研究