iOS App之間的通訊 -local socket,ios-local

來源:互聯網
上載者:User

iOS App之間的通訊 -local socket,ios-local

之前看到一篇文章介紹到App之間的五種通訊方式,它分別有URL Scheme,Keychain,UIPastedboard,UIDocumentInteractionController以及利用socket進行本地通訊。前面4種都有用到過,也相對比較簡單,幾行代碼的事。對於最後一種之前一直沒用到過(原諒我還是個小白),所以今天試著寫了下,這兒記錄在這裡和大家分享。

好了,廢話不多說,開始:

首先,說下它的原理,其實很簡單,一個App在本地的連接埠進行TCP的bind和listen,另外一個App在本地同一個連接埠進行connect,這樣就建立了一個正常的TCP串連,可以想傳什麼資料就傳什麼資料。下面開始先建立服務端:

1,首先用socket()函數建立一個通訊端

/* * socket返回一個int值,-1為建立失敗 * 第一個參數指明了協議族/域 ,通常有AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL * 第二個參數指定一個套介面類型:SOCK_STREAM,SOCK_DGRAM、SOCK_SEQPACKET等 * 第三個參數指定相應的傳輸協議,諸如TCP/UDP等,一般設定為0來使用這個預設的值 */int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1){  close(sock);  NSLog(@"socket error : %d",sock);
return;}

 2,綁定本機地址和連接埠號碼

// 地址結構體資料,記錄ip和連接埠號碼struct sockaddr_in sockAddr;// 聲明使用的協議sockAddr.sin_family = AF_INET;// 擷取原生ip,轉換成char類型的 const char *ip = [[self getIPAddress] cStringUsingEncoding:NSASCIIStringEncoding];// 將ip賦值給結構體,inet_addr()函數是將一個點分十進位的IP轉換成一個長整數型數sockAddr.sin_addr.s_addr = inet_addr(ip);// 設定連接埠號碼,htons()是將整型變數從主機位元組順序轉變成網路位元組順序sockAddr.sin_port = htons(12345);/* * bind函數用於將通訊端關聯一個地址,返回一個int值,-1為失敗 * 第一個參數指定通訊端,就是前面socket函數調用返回額通訊端 * 第二個參數為指定的地址 * 第三個參數為地址資料的大小 */int bd = bind(sock,(struct sockaddr *) &sockAddr, sizeof(sockAddr));if(bd == -1){  close(sock);  NSLog(@"bind error : %d",bd);  return;}

 3,監聽綁定的地址

/* * listen函數使用主動串連套接介面變為被串連介面,使得可以接受其他進程的請求,返回一個int值,-1為失敗 * 第一個參數是之前socket函數返回的通訊端 * 第二個參數可以理解為串連的最大限制 */int ls = listen(sock,20);if(ls == -1){  close(sock);  NSLog(@"listen error : %d",ls);  return;}

 4,下面就是等待用戶端的串連,使用accept()(由於accept函數會阻塞線程,在等待串連的過程中會一直卡著,所以建議將其放在子線程裡面)

// 1,開啟一個子線程NSTread *recvThread = [[NSThread alloc] initwithTarget:self selector:@selector(recvData) object: nil];[recvThread start];- (void)recvData{// 2,等待用戶端串連// 聲明一個地址結構體,用於後面接收用戶端返回的地址    struct sockaddr_in recvAddr;// 地址大小  socklen_t recv_size = sizeof(struct sockaddr_in);/* * accept()函數在串連成功後會返回一個新的通訊端(self.newSock),用於之後和這個用戶端之前收發資料 * 第一個參數為之前監聽的通訊端,之前是局部變數,現在需要改為全域的 * 第二個參數是一個結果參數,它用來接收一個傳回值,這個傳回值指定用戶端的地址 * 第三個參數也是一個結果參數,它用來接收recvAddr結構體的代銷,指明其所佔的位元組數 */self.newSock = accept(self.sock,(struct sockaddr *) &recvAddr, &recv_size);// 3,來到這裡就代表已經串連到一個新的用戶端,下面就可以進行收發資料了,主要用到了send()和recv()函數  ssize_t bytesRecv = -1; // 返回資料位元組大小  char recvData[128] = ""; // 返回資料緩衝區// 如果一端中斷連線,recv就會馬上返回,bytesrecv等於0,然後while迴圈就會一直執行,所以判斷等於0是跳出去  while(1){  bytesRecv = recv(self.newSocket,recvData,128,0); // recvData為收到的資料  if(bytesRecv == 0){    break;       }  }}

 5,發送資料

- (void)sendMessage{        char sendData[32] = "hello client";    ssize_t size_t = send(self.newSocket, sendData, strlen(sendData), 0);  }

 用戶端那邊就主要分為:建立通訊端,根據ip和連接埠號碼擷取服務端的主機地址,然後再串連,串連成功過後就能夠向服務端收發資料了,下面我們看代碼。

1,和服務端一樣用socket函數建立通訊端

int sock = socket(AF_INET, SOCK_STREAM,0);if(sock == -1){  NSLog(@"socket error : %d",sock);  return;}

 2,擷取主機的地址

NSString *host = [self getIPAddress]; // 擷取本機ip地址// 返回對應於給定主機名稱的包含主機名稱字和地址資訊的hostent結構指標struct hostent *remoteHostEnt = gethostbyname([host UTF8String]);if(remoteHostEnt == NULL){  close(sock);  NSLog(@"無法解析伺服器主機名稱");  return;}
// 配置通訊端將要串連主機的ip地址和連接埠號碼,用於connect()函數struct in_addr *remoteInAddr = (struct in_addr *)remoteHost->h_addr_list[0];struct sockaddr_in socktPram;socketPram.sin_family = AF_INT;socketPram.sin_addr = *remoteInAddr;socketPram.sin_port = htons([port intValue]);

 3,使用connect()函數串連主機

/* * connect函數通常用於用戶端簡曆tcp串連,串連指定地址的主機,函數返回一個int值,-1為失敗 * 第一個參數為socket函數建立的通訊端,代表這個通訊端要串連指定主機 * 第二個參數為通訊端sock想要串連的主機地址和連接埠號碼 * 第三個參數為主機地址大小 */int con = connect(sock, (struct sockaddr *) &socketPram, sizeof(socketPram));if(con == -1){  close(sock);  NSLog(@"串連失敗");  return;}NSLog("串連成功"); // 來到這代表串連成功;

4,串連成功之後就可以收發資料了

- (IBAction)senddata:(id)sender {    // 發送資料    char sendData[32] = "hello service";    ssize_t size_t = send(self.sock, sendData, strlen(sendData), 0);    NSLog(@"%zd",size_t);}- (void)recvData{    // 接受資料,放在子線程    ssize_t bytesRecv = -1;    char recvData[32] = "";    while (1) {            bytesRecv = recv(self.sock, recvData, 32, 0);        NSLog(@"%zd %s",bytesRecv,recvData);        if (bytesRecv == 0) {            break;        }    }}

 好了,利用socket在本地進行兩個App的通訊就這樣就行了。第一次寫博文,一是記錄下自己的心得,二是和大家一起分享,文中有不對的地方希望大家可以指出。最後附上Demo的地址,兩個項目,有興趣的大家可以下下來試下。https://pan.baidu.com/s/1nvcvC8p

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.