English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Esempio di comunicazione tra App iOS tramite local socket

Ho visto un articolo che introduceva cinque modi di comunicazione tra App, ognuno di essi ha URL Scheme, Keychain, UIPastedboard, UIDocumentInteractionController e comunicazione locale utilizzando socket. Le prime quattro sono state utilizzate, sono anche relativamente semplici, sono solo una manciata di righe di codice. Per l'ultimo non l'avevo mai utilizzato (perdonatemi se sono ancora un principiante), quindi oggi ho cercato di scriverlo, lo registro qui per condividerlo con tutti.

Bene, senza perdere tempo, iniziamo:

Prima di tutto, parliamo del suo principio, in realtà è molto semplice, un App sullo stesso portale locale esegue TCP bind e listen, un altro App sullo stesso portale locale esegue connect, in questo modo si stabilisce una connessione TCP normale, puoi trasmettere qualsiasi tipo di dati.Iniziamo a creare il server:

1, per prima cosa utilizzare la funzione socket() per creare un socket

/*
 * socket restituisce un valore int, -1 indica un fallimento nella creazione
 * Il primo parametro indica la famiglia di protocolli/ dominio, di solito AF_INET(IPV4), AF_INET6(IPV6), AF_LOCAL
 * Il secondo parametro specifica un tipo di socket: SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET ecc.
 * Il terzo parametro specifica il protocollo di trasmissione corrispondente, come TCP/UDP ecc., di solito impostato a 0 per utilizzare questo valore predefinito
 */
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){
 close(sock);
 NSLog(@"errore di socket : %d", sock);<br> return;
}

 2, binding dell'indirizzo e del numero di porta del computer

// Struttura di dati di indirizzo, registra l'indirizzo IP e il numero di porta
struct sockaddr_in sockAddr;
// Dichiarazione del protocollo utilizzato
sockAddr.sin_family = AF_INET;
// Ottieni l'indirizzo IP del computer, convertito in tipo char
const char *ip = [[self getIPAddress] cStringUsingEncoding:NSASCIIStringEncoding];
// Assegna l'indirizzo IP alla struttura, inet_addr() è la conversione di un IP decimale a virgola separata in un intero a lunghezza di lunghezza
sockAddr.sin_addr.s_addr = inet_addr(ip);
// Imposta il numero di porta, htons() è il passaggio da variabile intera di byte order host a network byte order
sockAddr.sin_port = htons(12345);
/*
 * La funzione bind utilizza il socket per associare un indirizzo, restituendo un valore int, -1 per fallimento
 * Il primo parametro specifica il socket, ossia il socket restituito dalla chiamata alla funzione socket in precedenza
 * Il secondo parametro è l'indirizzo specificato
 * Il terzo parametro è la dimensione dei dati di indirizzo
 */
int bd = bind(sock,(struct sockaddr *) &sockAddr, sizeof(sockAddr));
if(bd == -1){
 close(sock);
 NSLog(@"errore di binding : %d",bd);
 return;
}

 3, ascoltare l'indirizzo di binding

/*
 * La funzione listen utilizza un socket di connessione attiva per diventare un socket di connessione passiva, permettendo di accettare richieste da altri processi, restituendo un valore int, -1 per fallimento
 * Il primo parametro è il socket restituito dalla funzione socket in precedenza
 * Il secondo parametro può essere interpretato come il limite massimo di connessioni
 */
int ls = listen(sock,20);
if(ls == -1){
 close(sock);
 NSLog(@"errore di ascolto : %d",ls);
 return;
}

 4, qui inizia l'attesa della connessione del client, utilizzando accept()(dato che la funzione accept() blocca il thread, durante il processo di attesa della connessione rimarrà bloccato, quindi si consiglia di metterlo in un sottothread)

// 1, avvia un sottothread
NSTread *recvThread = [[NSThread alloc] initwithTarget:self selector:@selector(recvData) object: nil];
[recvThread start];
- (void)recvData{
// 2, attendere la connessione del client
// Dichiarare una struttura di indirizzo, utilizzata per ricevere l'indirizzo di ritorno del client in seguito 
 struct sockaddr_in recvAddr;
// Dimensione dell'indirizzo
 socklen_t recv_size = sizeof(struct sockaddr_in);
/*
 * La funzione accept() restituisce una nuova socket (self.newSock) dopo il successo della connessione, utilizzata per ricevere e inviare dati con questo client
 * Il primo parametro è la socket in ascolto, che prima era una variabile locale, ora deve essere resa globale
 * Il secondo parametro è un parametro di risultato, utilizzato per ricevere un valore di ritorno, che specifica l'indirizzo del client
 * Il terzo parametro è anche un parametro di risultato, utilizzato per ricevere il contenuto della struttura recvAddr, che indica il numero di byte occupati
 */
self.newSock = accept(self.sock,(struct sockaddr *) &recvAddr, &recv_size);
// 3, arrivati qui significa che è stata stabilita una connessione con un nuovo client, quindi si può procedere con la ricezione e l'invio di dati, utilizzando principalmente le funzioni send() e recv()
 ssize_t bytesRecv = -1; // dimensione dei byte dei dati di ritorno
 char recvData[128] = ""; // area di cache dei dati di ritorno
// Se una delle due estremità interrompe la connessione, recv tornerà immediatamente, bytesrecv sarà uguale a 0 e quindi il ciclo while continuerà a eseguire, quindi la condizione uguale a 0 è uscire dal ciclo
 while(1){
 bytesRecv = recv(self.newSocket,recvData,128,0); // recvData è i dati ricevuti
 if(bytesRecv == 0){
 break; 
 }
 }
}

 5, inviare dati

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

 Sul lato client, la principale distinzione è: creare una socket, ottenere l'indirizzo del server in base all'IP e al numero di porta, quindi connettersi, e una volta stabilita la connessione, si potrà ricevere e inviare dati al server. Vediamo il codice dopo.

1, creare un socket utilizzando la funzione socket come il server

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

 2, ottenere l'indirizzo dell'host

NSString *host = [self getIPAddress]; // Ottenere l'indirizzo IP locale
// Restituisce un puntatore alla struttura hostent che contiene il nome e l'indirizzo dell'host specificato
struct hostent *remoteHostEnt = gethostbyname([host UTF8String]);
if(remoteHostEnt == NULL){
 close(sock);
 NSLog(@"Impossibile risolvere il nome host del server");
 return;
<br>// Configurare l'indirizzo IP e il numero di porta dell'host che il socket deve connettersi, utilizzato dalla funzione 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, utilizzare la funzione connect() per connettersi all'host

/*
 * La funzione connect viene solitamente utilizzata per stabilire una connessione TCP client-side, connettersi a un host specifico, la funzione restituisce un valore int, -1 per fallimento
 * Il primo parametro è il socket creato dalla funzione socket, che rappresenta che questo socket deve connettersi a un host specifico
 * Il secondo parametro è l'indirizzo host e il numero di porta che il socket sock desidera connettersi
 * La terza parametro è la dimensione dell'indirizzo host
 */
int con = connect(sock, (struct sockaddr *) &socketPram, sizeof(socketPram));
if(con == -1){
 close(sock);
 NSLog(@"connessione fallita");
 return;
}
NSLog("connessione riuscita"); // Arrivare qui significa che la connessione è riuscita;

4, connessione riuscita dopo di che è possibile ricevere e inviare dati

- (IBAction)senddata:(id)sender {
 // Invio dati
 char sendData[32] = "hello service";
 ssize_t size_t = send(self.sock, sendData, strlen(sendData), 0);
 NSLog(@"%zd",size_t);
}
- (void)recvData{
 // Ricezione dati, messi in un thread secondario
 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;
  }
 }
}

 Bene, la comunicazione tra due app locali utilizzando socket è così. È la prima volta che scrivo un articolo, da una parte per registrare le mie esperienze, e dall'altra per condividerle con tutti. Spero che tutti possano segnalare eventuali errori nel testo. Infine, allego l'indirizzo del demo, due progetti, chi è interessato può scaricarli e provarli.

https://pan.baidu.com/s/1nvcvC8p

Ecco la raccolta di informazioni sulla comunicazione tra app iOS - local socket. Continueremo a integrare ulteriori informazioni in futuro, grazie per il supporto di tutti a questo sito!

Dichiarazione: il contenuto di questo articolo è stato raccolto da Internet, il copyright è dell'autore originale, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene i diritti di proprietà, non è stato editato manualmente e non assume alcuna responsabilità legale correlata. Se trovi contenuti sospetti di violazione del copyright, sei invitato a inviare una e-mail a: notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare, fornendo prove pertinenti. Una volta verificata, questo sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare