English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
I once read an article introducing five communication methods between Apps, which include URL Scheme, Keychain, UIPastedboard, UIDocumentInteractionController, and local communication using sockets. The previous4I have used all of them before, and they are relatively simple, just a few lines of code. For the last one, I haven't used it before (forgive me for still being a beginner), so I tried writing it today and I'm recording it here to share with everyone.
Alright, no more chatter, let's get started:
Firstly, let's talk about its principle, which is actually very simple. One App binds and listens on a local port for TCP, and another App connects to the same port locally, thus establishing a normal TCP connection. You can send any data you want through it.The process of creating the server-side begins below:
1First, create a socket using the socket() function
/* * socket returns an int value,-1Indicates creation failure * The first parameter specifies the protocol family/domain, usually AF_INET(IPV4) AF_INET6) IPV6) AF_LOCAL * The second parameter specifies a socket type: SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, etc. * The third parameter specifies the corresponding transmission protocol, such as TCP/UDP, etc., generally set to 0 to use this default value */ int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1{ close(sock); NSLog(@"socket error : %d", sock);<br> return; }
2,binding the local address and port number
// Address structure data, recording IP and port number struct sockaddr_in sockAddr; // Declare the protocol used sockAddr.sin_family = AF_INET; // Get the IP of the local machine, converted to a char type const char *ip = [[self getIPAddress] cStringUsingEncoding:NSASCIIStringEncoding]; // Assign ip to the structure, inet_addr() function is to convert a dotted decimal IP into a long integer type sockAddr.sin_addr.s_addr = inet_addr(ip); // Set the port number, htons() is to convert an integer variable from host byte order to network byte order sockAddr.sin_port = htons(12345; /* * The bind function is used to associate a socket with an address and returns an int value,-1Indicates failure * The first parameter specifies the socket, which is the socket returned by the previous socket function call * The second parameter is the specified address * The third parameter is the size of the address data */ int bd = bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)); if(bd == -1{ close(sock); NSLog(@"bind error : %d", bd); return; }
3,listening on the bound address
/* * The listen function converts an active connection socket interface to a connected interface, allowing it to accept requests from other processes, and returns an int value,-1Indicates failure * The first parameter is the socket returned by the previous socket function * The second parameter can be understood as the maximum limit of the connection */ int ls = listen(sock,20); if(ls == -1{ close(sock); NSLog(@"listen error : %d",ls); return; }
4below is waiting for the client's connection, using accept()(since the accept function will block the thread, it will keep blocking during the waiting process, so it is recommended to place it in a sub-thread)
// 1to start a sub-thread NSTread *recvThread = [[NSThread alloc] initWithTarget:self selector:@selector(recvData) object: nil]; [recvThread start]; - (void)recvData{ // 2,waiting for client connection // Declare an address structure to receive the client's returned address later struct sockaddr_in recvAddr; // address size socklen_t recv_size = sizeof(struct sockaddr_in); /* * The accept() function returns a new socket (self.newSock) after a successful connection, which is used for sending and receiving data with this client later * The first parameter is the previously listened socket, which was a local variable and now needs to be changed to global * The second parameter is a result parameter, used to receive a return value, which specifies the address of the client * The third parameter is also a result parameter, used to receive the address of the recvAddr structure, indicating the number of bytes it occupies */ self.newSock = accept(self.sock,(struct sockaddr *) &recvAddr, &recv_size); // 3arriving here means that a new client has been connected, and data transmission can be carried out below, mainly using send() and recv() functions ssize_t bytesRecv = -1]; // return data byte size char recvData[128] = ""; // return data buffer // If one end of the connection is disconnected, recv will return immediately, bytesrecv will be equal to 0, and then the while loop will keep executing, so checking for 0 is used to jump out while(1{ bytesRecv = recv(self.newSocket,recvData,128,0); // recvData is the received data if(bytesRecv == 0){ break; } } }
5send data
- (void)sendMessage{ char sendData[32]= "hello client"; ssize_t size_t = send(self.newSocket, sendData, strlen(sendData), 0); }
On the client side, it is mainly divided into: creating a socket, obtaining the host address of the server based on the IP and port number, and then connecting. After a successful connection, data can be sent and received from the server. Let's look at the code below.
1Also create a socket using the socket function like the server side
int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1{ NSLog(@"Socket error : %d", sock); return; }
2, get the host address
NSString *host = [self getIPAddress]; // Get the local IP address // Returns a hostent structure pointer containing host name and address information corresponding to the given hostname struct hostent *remoteHostEnt = gethostbyname([host UTF8String]); if(remoteHostEnt == NULL){ close(sock); NSLog(@"Unable to resolve server hostname"); return; }// Configure the IP address and port number of the host to be connected by the socket, used for the connect() function 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]);
3To connect to the host using the connect() function
/* * The connect function is usually used by the client to establish a TCP connection with the specified address of the host, the function returns an int value,-1Indicates failure * The first parameter is the socket created by the socket function, representing that this socket needs to connect to the specified host * The second parameter is the host address and port number that the socket sock wants to connect to * The third parameter is the size of the host address */ int con = connect(sock, (struct sockaddr *) &socketPram, sizeof(socketPram)); if(con == -1{ close(sock); NSLog(@"Connection failed"); return; } NSLog("Connection successful"); // Connected here indicates successful connection;
4After the connection is established, you can send and receive data.
- (IBAction)senddata:(id)sender { // Send data char sendData[32] = "hello service"; ssize_t size_t = send(self.sock, sendData, strlen(sendData), 0); NSLog(@"%zd", size_t); } - (void)recvData{ // Receive data, place in the child thread 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; } } }
That's all, the communication between two Apps locally using socket is done. This is my first blog post, first to record my own experience, and second to share with everyone. If there are any mistakes in the text, I hope everyone can point them out. Finally, I attach the address of the Demo, two projects, and those who are interested can download and try them out.
https://pan.baidu.com/s/1nvcvC8p
This is the summary of the communication between iOS Apps - local socket. We will continue to supplement relevant information, thank you for your support to this site!
Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email to report abuse, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.)