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

Ejemplo de comunicación entre aplicaciones iOS local socket

Anteriormente, vi un artículo que介绍的App entre las cinco formas de comunicación, que incluyen URL Scheme, Keychain, UIPastedboard, UIDocumentInteractionController y utilizar socket para la comunicación local. Antes4Todas han sido utilizadas, y son relativamente simples, solo unas pocas líneas de código. Para el último tipo, no lo he utilizado antes (perdón, aún soy un novato), así que hoy intenté escribirlo, aquí lo registro para compartir con todos.

Bien, sin más preámbulos, empecemos:

Primero, digamos su principio, que es muy simple, una aplicación en el puerto local realiza bind y listen de TCP, y otra aplicación en el mismo puerto local realiza connect, de esta manera se establece una conexión TCP normal, y se puede enviar cualquier tipo de datos.A continuación, comencemos creando el servidor:

1primero, cree un socket con la función socket()}

/*
 * socket devuelve un valor int,-1por crear fracaso
 * el primer parámetro indica la familia de protocolos/dominio, generalmente hay AF_INET(IPV4)、AF_INET6)、AF_INET6)、AF_LOCAL
 * el segundo parámetro especifica un tipo de interfaz de socket: SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, etc.
 * el tercer parámetro especifica el protocolo de transmisión correspondiente, como TCP/UDP, generalmente se establece en 0 para usar este valor predeterminado
 */
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1{
 close(sock);
 NSLog(@"error de socket : %d",sock);<br> return;
}

 2,enlazar la dirección y el número de puerto de la máquina

// datos de estructura de dirección, registrar ip y número de puerto
struct sockaddr_in sockAddr;
// declarar el protocolo utilizado
sockAddr.sin_family = AF_INET;
// obtener la dirección IP de la máquina, convertirla a tipo char
const char *ip = [[self getIPAddress] cStringUsingEncoding:NSASCIIStringEncoding];
// asignar ip a la estructura, inet_addr() es convertir una dirección IP de punto decimal a un entero largo
sockAddr.sin_addr.s_addr = inet_addr(ip);
// establecer el número de puerto, htons() es convertir una variable entera del orden de bytes del host al orden de bytes de red
sockAddr.sin_port = htons(12345;
/*
 * la función bind se utiliza para asociar un socket con una dirección, devolviendo un valor int,-1Para fallar
 * el primer parámetro especifica el socket, es decir, el socket devuelto por la llamada a la función socket anterior
 * el segundo parámetro es la dirección especificada
 * el tercer parámetro es el tamaño de los datos de la dirección
 */
int bd = bind(sock,(struct sockaddr *) &sockAddr, sizeof(sockAddr));
if(bd == -1{
 close(sock);
 NSLog(@"error de enlace : %d",bd);
 return;
}

 3,escuchar la dirección de enlace

/*
 * la función listen cambia el socket de conexión activa a un socket de conexión pasiva, lo que permite aceptar solicitudes de otros procesos, devolviendo un valor int,-1Para fallar
 * el primer parámetro es el socket devuelto por la función socket anterior
 * segundo parámetro puede entenderse como el límite máximo de conexión
 */
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);
}

 En el lado del cliente, se divide principalmente en: crear un socket, obtener la dirección del host del servidor según la IP y el número de puerto, luego conectarse, y después de conectarse con éxito, se puede recibir y enviar datos al servidor. Ahora veamos el código.

1Similarmente, y como el servidor, crear un socket utilizando la función socket

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

 2, obtener la dirección del host

NSString *host = [self getIPAddress]; // Obtener la dirección IP de la máquina local
// Devuelve un puntero de estructura hostent que contiene el nombre del host y la información de la dirección para el nombre de host dado
struct hostent *remoteHostEnt = gethostbyname([host UTF8String]);
if(remoteHostEnt == NULL){
 close(sock);
 NSLog(@"No se puede resolver el nombre de host del servidor");
 return;
}// Configurar la dirección IP y el número de puerto del host al que se conectará el socket, utilizado por la función 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]);

 3Conectar al host utilizando la función connect()

/*
 * La función connect se utiliza generalmente para que el cliente establezca una conexión TCP, conectándose al host especificado, y la función devuelve un valor int,-1Para fallar
 * El primer parámetro es el socket creado por la función socket, que representa que este socket se conectará al host especificado
 * El segundo parámetro es la dirección del host y el número de puerto que el socket sock desea conectarse
 * El tercer parámetro es el tamaño de la dirección del host
 */
int con = connect(sock, (struct sockaddr *) &socketPram, sizeof(socketPram));
if(con == -1{
 close(sock);
 NSLog(@"Conexión fallida");
 return;
}
NSLog("Conexión exitosa"); // Llegar aquí significa que la conexión se ha establecido con éxito;

4Después de que se establece la conexión, se puede recibir y enviar datos.

- (IBAction)senddata:(id)sender {
 // Enviar datos
 char sendData[32] = "hello service";
 ssize_t size_t = send(self.sock, sendData, strlen(sendData), 0);
 NSLog(@"%zd",size_t);
}
- (void)recvData{
 // Recibir datos, poner en el hilo secundario
 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;
  }
 }
}

 Bueno, la comunicación entre dos aplicaciones locales utilizando socket está lista. Esta es mi primera entrada en el blog, por un lado, para registrar mis reflexiones, y por otro lado, para compartir con todos. Espero que todos puedan señalar los errores en el texto. Finalmente, adjunto la dirección del Demo, dos proyectos, los que estén interesados pueden descargarlos para probar.

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

Aquí está la recopilación de información sobre la comunicación entre aplicaciones iOS - local socket. Continuaremos complementando la información relevante, ¡gracias por el apoyo de todos a este sitio!

Declaración: el contenido de este artículo se ha obtenido de la red, pertenece al propietario original, el contenido se ha contribuido y subido por los usuarios de Internet de manera voluntaria. Este sitio no posee los derechos de propiedad, no ha sido editado por humanos y no asume ninguna responsabilidad legal relacionada. Si encuentra contenido sospechoso de copyright, por favor envíe un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, por favor reemplace # con @) para denunciar, y proporcione evidencia relevante. Una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de infracción.

Te gustará también