English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
I saw an article before that introduced five communication methods between Apps, which include URL Scheme, Keychain, UIPastedboard, UIDocumentInteractionController, and local communication using sockets. Before that,4All of them have been used before, and they are relatively simple, just a few lines of code. The last one I haven't used before (forgive me, I am still a beginner), so I tried writing it today, and I am recording it here to share with everyone.
Alright, no more废话, let's get started:
Firstly, let's talk about its principle, which is actually very simple. An App binds and listens to a local port using TCP, and another App connects to the same port locally, thus establishing a normal TCP connection, allowing any data to be transmitted. Let's start by creating the server first:
1First use the socket() function to create a socket
/* * socket returns an int value-1For 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 transport protocol, such as TCP/UDP, etc., usually 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; } /* * socket returns an int value-1For 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 transport protocol, such as TCP/UDP, etc., usually 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; }
2Bind the local machine 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 the ip to the structure, inet_addr() function is used to convert a dotted decimal IP to a long integer sockAddr.sin_addr.s_addr = inet_addr(ip); // Set the port number, htons() is used 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-1For 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; }
3Listen on the bound address
/* * The listen function changes the active connection socket interface to a passive connection interface, allowing it to accept requests from other processes and return an int value.-1For failure * The first parameter is the socket returned by the previous socket function * The second parameter can be understood as the maximum limit of connections */ int ls = listen(sock,2,0); if(ls == -1){ close(sock); NSLog(@"listen error : %d",ls); return; }
4Waiting for client connection, using accept()(Since the accept function will block the thread, it will be stuck during the waiting process, so it is recommended to put it in a child thread)
// 1.Start a child 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 address returned by the client 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 a global variable * The second parameter is a result parameter, used to receive a return value, which specifies the client's address * 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); // 3.This means that a new client has been connected, and data can be sent and received now, mainly using the 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.
1Like the server, create a socket using the socket function
int sock = socket(AF_INET, SOCK_STREAM,0); if(sock == -1){ NSLog(@"socket error : %d",sock); return; }
2Get the host address
NSString *host = [self getIPAddress]; // Get the local IP address // Returns a hostent structure pointer containing the 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]);
3Using the connect() function to connect to the host
/* * The connect function is usually used by the client to establish a TCP connection, connect to the specified address of the host, and return an int value-1For 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"); // Being here means the connection is successful;
4After the connection is successful, you can send and receive data.
- (IBAction)senddata:(id)sender { // Sending data char sendData[32] = "hello service"; ssize_t size_t = send(self.sock, sendData, strlen(sendData), 0); NSLog(@"%zd", size_t); } - (void)recvData{ // Receiving data, placed in a sub-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; } } }
Alright, that's it for using sockets to communicate between two apps locally. This is my first blog post, and I'm writing it to record my own experiences and to share with everyone. If there are any mistakes in the text, I hope everyone can point them out. Finally, I'll attach the Demo address, two projects, and those who are interested can download and try them out:
That's all for this article. I hope it will be helpful to everyone's learning and that everyone will support the Yelling Tutorial more.
Declaration: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, does not undergo人工 editing, and does not assume 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 infringement, and provide relevant evidence. Once verified, this site will immediately delete the infringing content.)