English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
之前看到一篇文章介绍到App之间的五种通信方式,它分别有URL Scheme,Keychain,UIPastedboard,UIDocumentInteractionController以及利用socket进行本地通信。前面4种都有用到过,也相对比较简单,几行代码的事。对于最后一种之前一直没用到过(原谅我还是个小白),所以今天试着写了下,这儿记录在这里和大家分享。
好了,废话不多说,开始:
首先,说下它的原理,其实很简单,一个App在本地的端口进行TCP的bind和listen,另外一个App在本地同一个端口进行connect,这样就建立了一个正常的TCP连接,可以想传什么数据就传什么数据。下面开始先创建服务端:
1,d'abord utiliser la fonction socket() pour créer un descripteur de socket
/* * socket renvoie une valeur int,-1pour la création échouée * le premier paramètre indique la famille de protocole/domaine, généralement AF_INET(IPV4)、AF_INET6)、AF_INET6)、AF_LOCAL * le second paramètre spécifie un type de socket : SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, etc. * le troisième paramètre spécifie le protocole de transmission correspondant, tel que TCP/UDP, etc., généralement définie sur 0 pour utiliser cette valeur par défaut */ int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1{ close(sock); NSLog(@"erreur de socket : %d",sock);<br> return; }
2,lier l'adresse et le numéro de port de l'ordinateur local
// données de structure d'adresse, enregistrer l'adresse IP et le numéro de port struct sockaddr_in sockAddr; // déclarer le protocole utilisé sockAddr.sin_family = AF_INET; // obtenir l'adresse IP de l'ordinateur local, convertie en type char const char *ip = [[self getIPAddress] cStringUsingEncoding:NSASCIIStringEncoding]; // affecter ip à la structure, inet_addr() est une fonction qui convertit une adresse IP en point décimal en un entier long sockAddr.sin_addr.s_addr = inet_addr(ip); // définir le numéro de port, htons() est une conversion d'un variable entier de l'ordre des octets de l'hôte vers l'ordre des octets réseau sockAddr.sin_port = htons(12345; /* * la fonction bind est utilisée pour associer un adresse au descripteur de socket, et renvoie une valeur int,-1pour l'échec * le premier paramètre spécifie le descripteur de socket, c'est-à-dire le descripteur de socket renvoyé par l'appel de la fonction socket précédente * le second paramètre est l'adresse spécifiée * le troisième paramètre est la taille des données d'adresse */ int bd = bind(sock,(struct sockaddr *) &sockAddr, sizeof(sockAddr)); if(bd == -1{ close(sock); NSLog(@"erreur de bind : %d",bd); return; }
3,écouter l'adresse de liaison
/* * la fonction listen transforme l'interface de connexion active en interface de connexion passée, permettant d'accepter les demandes d'autres processus, et renvoie une valeur int,-1pour l'échec * le premier paramètre est le descripteur de socket renvoyé par la fonction socket * le second paramètre peut être compris comme la limitation maximale de connexion */ 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); }
Du côté client, il est principalement divisé en : création de socket, obtention de l'adresse de l'hôte du serveur en fonction de l'IP et du port, puis connexion, après une connexion réussie, il est possible de recevoir et d'envoyer des données au serveur, nous allons voir le code maintenant.
1,comme le serveur, créer un socket avec la fonction socket
int sock = socket(AF_INET, SOCK_STREAM,0); if(sock == -1{ NSLog(@"Erreur socket : %d",sock); return; }
2, obtenir l'adresse de l'hôte
NSString *host = [self getIPAddress]; // Obtenir l'adresse IP du système local // Retourne un pointeur sur la structure hostent correspondant au nom d'hôte donné, contenant le nom et l'adresse de l'hôte struct hostent *remoteHostEnt = gethostbyname([host UTF8String]); if(remoteHostEnt == NULL){ close(sock); NSLog(@"Impossible de résoudre le nom d'hôte du serveur"); return; }// Configurer l'adresse IP et le port de l'hôte auquel le socket va se connecter, utilisé par la fonction 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,connecter à l'hôte en utilisant la fonction connect()
/* * La fonction connect() est généralement utilisée par le client pour établir une connexion TCP, se connecter à l'hôte spécifié, et renvoie une valeur int-1pour l'échec * le premier paramètre est le socket créé par la fonction socket, représentant que ce socket doit se connecter à l'hôte spécifié * le deuxième paramètre est l'adresse et le port que le socket sock souhaite se connecter * le troisième paramètre est la taille de l'adresse hôte */ int con = connect(sock, (struct sockaddr *) &socketPram, sizeof(socketPram)); if(con == -1{ close(sock); NSLog(@"Échec de la connexion"); return; } NSLog("Connection réussie"); // Arrivée ici signifie que la connexion a réussi ;
4Après la connexion réussie, vous pouvez envoyer et recevoir des données.
- (IBAction)senddata:(id)sender { // Envoyer des données char sendData[32] = "hello service"; ssize_t size_t = send(self.sock, sendData, strlen(sendData), 0); NSLog(@"%zd",size_t); } - (void)recvData{ // Recevoir des données, les placer dans un thread secondaire 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; } } }
C'est tout pour la communication entre deux applications locales via socket. C'est ma première publication, je veux d'abord enregistrer mes réflexions et ensuite les partager avec vous. Si vous trouvez des erreurs dans l'article, n'hésitez pas à les signaler. Enfin, je joins l'adresse du démon. Deux projets, ceux qui sont intéressés peuvent les télécharger et les essayer.
https://pan.baidu.com/s/1nvcvC8p
Voici la compilation des informations sur la communication entre les applications iOS - local socket. Nous continuerons à ajouter des informations pertinentes par la suite, merci de votre soutien à ce site !
Déclaration : le contenu de cet article est tiré d'Internet, propriété des auteurs respectifs, contribué et téléversé par les utilisateurs d'Internet de manière spontanée. Ce site ne détient pas de droits de propriété, n'a pas été édité par l'homme, et n'assume aucune responsabilité juridique connexe. Si vous trouvez du contenu suspect de violation de droits d'auteur, veuillez envoyer un email à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un email pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)