前言

本篇博客重点分析 Android 端 运行的远程命令工具 remote 模块 ;

该 Android 远程端模块 是 Android 平台的可执行程序 , 使用 NDK 进行编译的可执行程序 , 配合 PC 端的工具进行内存修改 ;





一、Android 端可执行程序的 main 函数操作



Android 端可执行程序主函数的主体就是一个死循环 , 在该循环中 , 通过 TCP 协议 , 接收来自 PC 端的指令 , 根据不同的指令 , 执行不同的操作 ;


开始执行后 , 阻塞等待 PC 端连接 , 连接成功后 , 继续向后执行 ;

		/* 等待 PC 端连接 , PC 端与 Android 端连接成功后 , 继续向后执行 */
		client.WaitForServer();

之后 , 还是阻塞等待 , 这次是等待 PC 端发送来的命令 ;

/* 等待 PC 端命令 */
client.WaitForCommand(root)

最后 , 根据获取的不同的命令 , 执行不同操作 , 这些操作 , 需要开发者自己进行开发 , 不同的应用 , 对应的操作也是不同的 ;


main 函数代码 :

int main()
{
	/* Android 端可执行程序主函数的主体就是一个死循环 , 
	 * 在该循环中 , 通过 TCP 协议 , 接收来自 PC 端的指令 , 
	 * 根据不同的指令 , 执行不同的操作
	 */
	do {
		Client client;
		char data[] = HELLO_INFO;
		const char* pinfo = "client prepare done! wait for pc!  \n";
		DECRYPT(data, pinfo);
		printf("%s\n", data);
		printf("%s", pinfo);

		/* 等待 PC 端连接 , PC 端与 Android 端连接成功后 , 继续向后执行 */
		client.WaitForServer();
		/* 连接成功提示 */
		printf("get a connection!\n");
		Json::Value root;
		do {
			/* 等待 PC 端命令 */
			if (client.WaitForCommand(root) == 0) {
				switch (root["cmd"].asInt()) {
				case CMD_READ_DATA:
					root.clear();
					client.ReadData(root);
					break;
				case CMD_WRITE_GOLD:
					client.WriteGold(root);
					break;
				case CMD_WRITE_EXP:
					client.WriteExp(root);
					break;
				default:
					break;
				}
			}
			/* 如果连接断开 , 那么重置连接 , 继续等待用户连接 */
			else if (!client.isConnected()) {
				client.Reset();
				printf("connection is lost!\nretry!\n");
				break;
			}
		} while (client.isValid());
	} while (1);
	return 0;
}

Android 端可执行程序的 mian.c 代码位置 :

在这里插入图片描述





二、Android 端 TCP 协议服务器建立



从 TCP 网络协议角度看 , 在 Android 端运行的是 服务器端 , 在 PC 端运行的是 客户端 ;

Android 端的服务器建立 :

  • ① 先绑定服务器 IP 地址 : 端口号
  • ② 监听端口号
  • ③ 阻塞等待客户端连接

PC 端的客户端 : 客户端只需要连接 绑定的服务器 IP 地址 + 端口号即可 ;


服务器建立代码 :

	/* 建立服务器 
	 * ① 先绑定服务器 IP 地址 : 端口号 
	 * ② 监听端口号
	 * ③ 阻塞等待客户端连接 
	 * 客户端只需要连接 绑定的服务器 IP 地址 + 端口号即可
	 */
	bool WaitForServer() {
		int ret = 0;
		struct sockaddr_in addr, client;
		addr.sin_family = AF_INET;
		addr.sin_port = 0x3725;//0x2537=9527
		/* 如果是 模拟器可以设置 127.0.0.1 , 
		   如果是真机 , 需要填写局域网内真实 IP 地址 */
		addr.sin_addr.s_addr = inet_addr("127.0.0.1");

		/* 绑定 IP 地址 和 端口号 */
		ret = bind(m_socket, (sockaddr*)&addr, sizeof(sockaddr_in));
		if (ret < 0) {
			printf("error info:%d %s\n", errno, strerror(errno));
			return false;
		}

		/* 监听端口号 */
		ret = listen(m_socket, SOMAXCONN);
		if (ret < 0) {
			printf("error info:%d %s\n", errno, strerror(errno));
			return false;
		}
		char buffer[4096] = "";
		int size = sizeof(client);

		/* 阻塞等待客户端连接 */
		int c = accept(m_socket, (sockaddr*)&client, &size);
		if (c == INVALID_SOCKET) {
			return false;
		}
		m_client = c;
		return ret >= 0;
	}




三、Android 端接收 PC 端传来的数据



调用 recv 方法 , 阻塞接收 PC 端传输来的数据 , 然后解析 json 字符串 , 将解析结果保存到 command 中 ;


代码如下 :

	/* 接收 PC 端传输来的数据 
	 * 然后解析 json 字符串 
	 * 将解析结果保存到 command 中
	 */
	int WaitForCommand(Json::Value& command) {
		char buffer[4096] = "";
		int ret = recv(m_client, (void*)buffer, sizeof(buffer), 0);
		if (ret > 0) {
			ret = 0;
			Json::Reader reader;
			if (reader.parse(buffer, buffer + strlen(buffer), command)) {
				ret = 0;
			}
			else {
				ret = -1;
			}
		}
		else {
			close(m_client);
			m_client = INVALID_SOCKET;
		}
		return ret;
	}




四、博客资源



下载地址 : https://download.csdn.net/download/han1202012/38499199

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐