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

Kommunikation zwischen iOS-Apps über local socket

Ich habe ein Artikel gesehen, der über die fünf Kommunikationsmethoden zwischen Apps spricht. Diese sind URL Scheme, Keychain, UIPastedboard, UIDocumentInteractionController und die Nutzung von Sockets für lokale Kommunikation. Vorher4Das ist alles, was ich verwendet habe, und es ist relativ einfach, nur einige Zeilen Code. Für das Letzte habe ich es bisher noch nie verwendet (verzeihen Sie mir, ich bin noch ein Anfänger), also habe ich es heute versucht und hier aufgeschrieben, um es mit Ihnen zu teilen. 

Nun, ohne lange um den heißen Brei zu reden, beginnen wir: 

Zunächst einmal, lassen Sie uns über den Prinzip des App-Prinzips sprechen, das eigentlich sehr einfach ist: Ein App bindet und hört auf einem lokalen Port auf TCP, während ein anderes App auf denselben Port verbindet. Auf diese Weise wird eine normale TCP-Verbindung hergestellt, und Sie können beliebige Daten übertragen. Beginnen wir mit der Erstellung des Servers: 

1、zunächst mit der Funktion 'socket()' einen Socket erstellen 

/*
* Gibt 'socket' einen int-Wert zurück,-1Für den Fall des Fehlschlags der Erstellung
* Der erste Parameter gibt die Protokollfamilie an/Domäne, normalerweise AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL
* Der zweite Parameter spezifiziert einen Socket-Typ: SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET usw.
* Der dritte Parameter spezifiziert das entsprechende Übertragungsprotokoll, wie TCP/UDP usw., wird in der Regel 0 eingestellt, um diesen Standardwert zu verwenden
*/
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){
close(sock);
NSLog(@"socket error : %d",sock);<br> return;
}
/*
 * Gibt 'socket' einen int-Wert zurück,-1Für den Fall des Fehlschlags der Erstellung
 * Der erste Parameter gibt die Protokollfamilie an/Domäne, normalerweise AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL
 * Der zweite Parameter spezifiziert einen Socket-Typ: SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET usw.
 * Der dritte Parameter spezifiziert das entsprechende Übertragungsprotokoll, wie TCP/UDP usw., wird in der Regel 0 eingestellt, um diesen Standardwert zu verwenden
 */
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){
 close(sock);
 NSLog(@"socket error : %d",sock);<br> return;
}

2、绑定本机地址和端口号 

// Adressstrukturdaten, die IP und Portnummer aufzeichnen
struct sockaddr_in sockAddr;
// Verwendung des Protokolls erklären
sockAddr.sin_family = AF_INET;
// IP des eigenen Computers abrufen und in einen char-Typ umwandeln
const char *ip = [[self getIPAddress] cStringUsingEncoding:NSASCIIStringEncoding];
// IP zuweisen, inet_addr() wandelt eine dezimale IP in einen Long-Integer um
sockAddr.sin_addr.s_addr = inet_addr(ip);
// Portnummer setzen, htons() wandelt einen Integer-Wert von der Hostenbyte-Reihenfolge in die Netzwerkbyte-Reihenfolge um
sockAddr.sin_port = htons(12345;
/*
 * Die Funktion 'bind' wird verwendet, um den Socket mit einer Adresse zu verknüpfen und gibt einen int-Wert zurück,-1Fehler
 * Der erste Parameter spezifiziert den Socket, der durch den Aufruf der Funktion 'socket' zurückgegeben wird
 * Der zweite Parameter ist die angegebene Adresse
 * Der dritte Parameter ist die Größe der Adressdaten
 */
int bd = bind(sock,(struct sockaddr *) &sockAddr, sizeof(sockAddr));
if(bd == -1){
 close(sock);
 NSLog(@"bind error : %d",bd);
 return;
}

3、监听绑定的地址

/*
 * Die Funktion 'listen' verwandelt den aktiven Socket in einen passiven Socket, um Anfragen anderer Prozesse anzunehmen und gibt einen int-Wert zurück,-1Fehler
 * Der erste Parameter ist der Socket, der durch die Funktion socket() zurückgegeben wurde
 * Der zweite Parameter kann als maximale Anzahl der Verbindungen verstanden werden
 */
int ls = listen(sock,20);
if(ls == -1){
 close(sock);
 NSLog(@"listen error : %d",ls);
 return;
}

4、Warten auf die Verbindung des Clients, verwenden Sie accept()(Da die Funktion accept() den Thread blockiert, bleibt der Thread während des Wartens auf die Verbindung hängen. Daher wird empfohlen, ihn in einem Unterthread auszuführen) 

// 1. Eröffnen eines Unterthreads
NSTread *recvThread = [[NSThread alloc] initwithTarget:self selector:@selector(recvData) object: nil];
[recvThread start];
- (void)recvData{
// 2. Warten auf die Verbindung des Clients
// Eine Adressstruktur wird deklariert, um die von dem Client zurückgegebenen Adressen zu empfangen 
 struct sockaddr_in recvAddr;
// Größe der Adresse
 socklen_t recv_size = sizeof(struct sockaddr_in);
/*
 * Die Funktion accept() gibt nach einem erfolgreichen Verbindungsaufbau einen neuen Socket (self.newSock) zurück, der für die zukünftige Datenübertragung mit diesem Client verwendet wird
 * Der erste Parameter ist der zuvor angehört Socket, der zuvor ein lokaler Variablenname war, muss jetzt global werden
 * Der zweite Parameter ist ebenfalls ein Ergebnisparameter, der verwendet wird, um einen Rückgabewert zu empfangen, der die Adresse des Clients angibt
 * Der dritte Parameter ist ebenfalls ein Ergebnisparameter, der verwendet wird, um die Adresse der recvAddr-Struktur zu empfangen, die die Anzahl der Bytes angibt, die sie belegt
 */
self.newSock = accept(self.sock,(struct sockaddr *) &recvAddr, &recv_size);
// 3. Hier bedeutet es, dass eine neue Client-Verbindung hergestellt wurde, und man kann jetzt Daten senden und empfangen. Hauptlich werden die Funktionen send() und recv() verwendet
 ssize_t bytesRecv = -1; // Rückgabegröße der Daten
 char recvData[128] = ""; // Rückgabecache
// Wenn eine Verbindung abgebrochen wird, kehrt recv sofort zurück, bytesrecv ist 0, und der while-Loop führt dann immer weiter aus. Daher wird der Wert 0 verwendet, um herauszugehen
 while(1){
 bytesRecv = recv(self.newSocket,recvData,128,0); // recvData ist die empfangene Daten
 if(bytesRecv == 0){
 break; 
 }
 }
}

5、Senden von Daten 

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

Bei der Client-Seite wird hauptsächlich in: Erstellen eines Sockets, Abrufen der Host-Adresse des Servers basierend auf IP und Port, dann Verbinden, nach dem erfolgreichen Verbinden können Daten zum Server gesendet und empfangen werden, unten sehen wir den Code. 

1Verwenden Sie wie der Server die Funktion socket() zum Erstellen eines Sockets 

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

2Adresse des Hosts abrufen 

NSString *host = [self getIPAddress]; // IP-Adresse des lokalen Computers abrufen
// Gibt einen Zeiger auf eine hostent-Struktur zurück, die Informationen über den Hostnamen und die Adresse enthält, die auf den gegebenen Hostnamen zutreffen
struct hostent *remoteHostEnt = gethostbyname([host UTF8String]);
if(remoteHostEnt == NULL){
 close(sock);
 NSLog(@"Der Hostname des Servers kann nicht interpretiert werden");
 return;
}<br>// Konfigurieren Sie die IP-Adresse und den Port des Hosts, den das Socket verbinden soll, um die Funktion connect() zu verwenden
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]);

3Verbindung zum Host über die Funktion connect() herstellen 

/*
 * Die connect-Funktion wird normalerweise für die Herstellung von TCP-Verbindungen durch den Client verwendet, um eine Verbindung zu einem bestimmten Host herzustellen, die Funktion gibt einen int-Wert zurück,-1Fehler
 * erster Parameter ist das Socket, das durch die socket-Funktion erstellt wurde, es repräsentiert, dass dieses Socket eine Verbindung zu einem bestimmten Host herstellen soll
 * zweiter Parameter ist die Host-Adresse und der Port, den das Socket sock verbinden möchte
 * dritte Parameter ist die Größe der Host-Adresse
 */
int con = connect(sock, (struct sockaddr *) &socketPram, sizeof(socketPram));
if(con == -1){
 close(sock);
 NSLog(@"Verbindung fehlgeschlagen");
 return;
}
NSLog("Verbindung erfolgreich"); // Dieser Ort bedeutet, dass die Verbindung erfolgreich hergestellt wurde;

4Nachdem die Verbindung erfolgreich hergestellt wurde, können Daten empfangen und gesendet werden 

- (IBAction)senddata:(id)sender {
 // Daten senden
 char sendData[32] = "hello service";
 ssize_t size_t = send(self.sock, sendData, strlen(sendData), 0);
 NSLog(@"%zd",size_t);
}
- (void)recvData{
 // Datenempfang, in einem Untertask ablegen
 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;
  }
 }
}

Nun, so funktioniert die Kommunikation zwischen zwei Apps lokal über socket. Dies ist mein erster Blogbeitrag. Einerseits möchte ich meine Gedanken festhalten, andererseits möchte ich sie mit Ihnen teilen. Falls es in dem Text Ungenauigkeiten gibt, freuen wir uns über Ihre Korrekturen. Schließlich fügen wir die Adresse des Demos hinzu. Zwei Projekte, diejenigen, die Interesse haben, können sie herunterladen und ausprobieren:

Das ist der gesamte Inhalt dieses Artikels. Wir hoffen, dass er Ihnen beim Lernen hilft und wir hoffen, dass Sie unsere Anleitung weiterempfehlen.

Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet übernommen und gehört dem Urheberrecht des Urhebers. Der Inhalt wurde von Internetbenutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Haftung. Wenn Sie urheberrechtlich relevante Inhalte entdecken, sind Sie herzlich eingeladen, eine E-Mail an notice#w zu senden.3codebox.com (Bitte ersetzen Sie # durch @ beim Senden von E-Mails zur Meldung von Verstößen und geben Sie relevante Beweise an. Sobald nachgewiesen, wird diese Website die beanstandeten urheberrechtlichen Inhalte sofort löschen.)

Empfohlene Artikel