允许远程调试的简单易用的 debug 工具 AConsole
因为需要实现了一个可以远程调试的工具 AConsole,现在来分享给大家。
请去 https://www.gitHub.com/iKCourage/iSunday 获取 iSunday.exe 和 ingz 目录下的 imoon_plugins.ingz 和 AConsole.ingz,并依次安装。然后就可以打开桌面上的 AConsole.ing 了。
特性支持:
通过 Socket (TCP) 连接进行调试:
但过程中可以断开连接,使用一个名字标识会话,即使调试过程中连接意外断开也可以继续调试。
使用 JSON 字符串来发送消息(尽可能的简单高效)。
多标签调试:
支持多个应用程序同时进行调试,每一个都会打开新的标签页。
可以是多个不同的应用程序。
日志信息可以设置类别,会显示成不同的颜色:
可以通过自定义配置来区分消息,自定义的配置相当简单,只是一个数字和对应的颜色。
发送的消息里也需要描述一个数字(但这足够简单,因为使用 JSON,所以只是一个字段数值)。
执行对象标记:
同一个应用程序中的每一条消息都可以指定一个执行对象(用来描述是谁发送了这条消息,如:类名或方法名),然后可以使用快速过滤。
推荐使用此项,因为这会使显示更整齐,并且过滤起来更快。
发送的消息里需要描述一个字符串。
过滤系统:
通过字符串或正则进行匹配消息,可以指定查找部分(执行对象部分,或消息部分)。
还可以根据类别来过滤,如:普通消息,警告,错误等。
一直觉得日志内容就应该支持查找的嘛。
自动打开应用程序:
这一项有些泛泛。可以通过配置自己的执行文件进行自动化编译或调试,然后会每隔一定时间检查一次是否有文件的状态发生变化,如果发生,则调用系统 api 打开自定义的执行文件(并可添加执行参数),从而实现自动化。(此功能比较鸡肋,很多人都实现了,不过还是带着吧,有些时候确实很好用)
可以同时支持多个执行文件和参数。
可以自己配置合适的检查时间。
大家可以通过自定义类别来设定一个适合自己的显示规则,从而方便调试,就像给 IDE 配色一样(总有自己喜欢的)。
然后可以直接看示例部分了。
另外赠送的功能(不是人人都会用到,希望可以帮到需要的人):
在 Socket 里实现了一个简单的辅助服务器,可以用来进行一些简单的测试。
如:需要模拟真实多用户登录的时候,可以每个应用程序都连接服务器,然后会获得一个 id,然后通过此 id 定位已经配置好的数组进行用户名和密码的登录。
实现的功能有:
建立连接时返回用户 id,id 是可以回收的,当有连接断开时,该 id 将被回收。通过此可以模拟多个真实用户。
建立连接时可以指定用户所在的组 id,然后会返回组内的用户 id。通过此可以将这个单服务器变成多服务器,每个组都互不影响,从而可以支持多个互不相关的程序同时进行调试。
当有新用户进入时,广播给所有已经建立连接的用户(包含组 id 和用户 id)。
当有新用户断开时,广播给所有已经建立连接的用户(包含组 id 和用户 id)。
通过服务器广播回来的其他用户的 id,应用程序间就可以进行通信啦。如:转发,或者广播。并且支持转发,广播给一个或多个用户,甚至是不同组的一个或多个用户。(调侃一下:貌似是没必要有的功能)
可以进行简单的数据写入和读取,从而进行用户间的数据共享。如:id 为 1 的用户将共享数据写入到服务器,然后 id 为 2 的用户可以向服务器索取 id 为 1 的用户的数据。(实现此功能时,我正好在写 p2p 的东西,而外网服务器每次都会返回一个随机的 64 位的 id,当两个用户进行连接时需要通过这个 64 位长的 id,烦扰之余就实现了这么个功能。我可以通过一个数字进行对话了。)当然,不一定大家都会用到,不过如果你凑巧需要的话,希望可以帮到你。
注:所有服务器返回的消息(或广播)都可以忽略不进行处理。你只需要实现自己需要的功能就好了(发送或者接收)。更方便大家进行测试。
一个简单的 JSON 编辑和校验工具。
一个批量文件复制工具。即使从事文职工作也能使用。(复制文件时可以通过正则表达式进行过滤来复制一部分内容。通过正则表达式可以实现非常强大的复制规 则,不过有些学习成本。幸好大家不太可能会有这种需求,这种需求很少见。在这里写出来不是告诉你这个功能多么好,而是希望在大家需要的时候可以帮到大 家。)
示例:
消息格式:
{"name": "player", "title": "播放器", "executor": "[WHERE]", "type": "print", "data": “message”, "_type": 0}
name: 一定要有(就像网页里的 url,会通过这里来打开一个标签页)
title: 标题
executor: 执行者(什么地方执行的,可以没有,但会使用一个默认的。通过这里也可以快速查找消息)
type: "print" 打印消息(内容恒为 print)
data: 消息内容(可以是字符串,也可以是数组,会自动转换为字符串。在外部设计的时候可以使用变参方式,而不用拼接字符串)
_type: 消息的类型(可以自定义任何类型,然后就可以通过过滤来查看指定类型的消息了。如果没有,则使用默认 0)
好了,这就是通过 Scoket 发送的消息内容,很简单明了吧。
Socket 发送格式:
4 字节的包头,一个 int。(标识后面这个包的字节大小,避免粘包)
4 字节的通信标识 。(恒为数字 7)(大家不要纠结这里哈,没必要用 4 个字节,但这样大家用起来都方便不是么。)
UTF 的字符串字节。
注:4 字节的包头只包含后面数据内容的大小,不包含这里的 4 个字节的包头。
这样就可以进行调试了,还算简单吧。
你也看到了,调试时的通信标识恒为 7,因为 0 - 6 已经用来实现 Socket 服务器的其他功能了。调试的时候只需要发送消息就可以了,不用管服务器的返回值(希望能简单一点,其实也没有必要哈)。不过服务器依然会返回标识为 7 的数据,用来通知你反送成功了(如果你需要的话)。
好了,来简单介绍下所有的标识吧,大家可以直接看标识为 7 的内容。
说明:以下 >> 为发送的数据,<< 为服务器返回的数据。
>> 0:客户端注册用户,即让服务器返回一个 id
bytes.writeInt(4 + 4);
bytes.writeInt(CSEnum.INIT); // 此数值为 0
bytes.writeInt(group); // 用户所在组的 id,由用户自己指定,可以不发送(默认为 0)只发送标识
socket.writeBytes(bytes);
socket.flush();
<< 0:服务器返回给用户一个 id
bytes.writeInt(4 + 4); // 服务器也返回一个包头
bytes.writeInt(CSEnum.INIT); // 0
bytes.writeInt(id); // 用户的 id(之所以没有返回用户的组 id 是因为用户自己知道)
socket.writeBytes(bytes);
socket.flush();
<< 3:服务器广播给所有人新注册用户的组 id 和用户 id
bytes.writeInt(4 + 4 + 4);
bytes.writeInt(CSEnum.INIT_ALL);
bytes.writeInt(id);
bytes.writeInt(group);
>> 1:客户端读取其他用户 id 的数据(也可以是自己的)
bytes.writeInt(4 + 4 + 4);
bytes.writeInt(CSEnum.READ);
bytes.writeInt(id);
bytes.writeInt(group);
<< 1:服务器返回给用户读取的数据
bytes.writeInt(4 + data.length);
bytes.writeInt(CSEnum.READ);
bytes.writeBytes(data);
>> 2:客户端写入自己的数据
bytes.writeInt(4 + data.length);
bytes.writeInt(CSEnum.WRITE);
bytes.writeBytes(data);
<< 2:服务器返回写入成功
bytes.writeInt(4);
bytes.writeInt(CSEnum.WRITE);
<< 4:服务器在有客户端连接断开时广播给其他用户
bytes.writeInt(4 + 4 + 4);
bytes.writeInt(CSEnum.CLOSE_ALL);
bytes.writeInt(id);
bytes.writeInt(group);
>> 5:客户端通过服务器来将消息转发给其他人(这里有点复杂,因为转发功能有点多,不需要就不用看了)
接下来就有点麻烦了(其实很简单,因为好多都用不到),先描述下转发规则:
0 所有组的所有人
bytes.writeInt(4 + 4 + data.length);
bytes.writeInt(CSEnum.RELAY);
bytes.writeInt(0); // 转发规则标识
bytes.writeBytes(data);
1 默认组的几个人
bytes.writeInt(4 + 4 + (4 + 4 * 3) + data.length); // 4 * 3 为用户的 id 占的字节,如:这里为 3,所以还得乘 4
bytes.writeInt(CSEnum.RELAY);
bytes.writeInt(1); // 转发规则标识
bytes.writeInt(id.length); // 这里为 3(用户个数)
bytes.writeInt(2); // id 为 2 的用户
bytes.writeInt(3); // id 为 3 的用户
bytes.writeInt(4); // id 为 4 的用户
bytes.writeBytes(data);
2 默认组的所有人
bytes.writeInt(4 + 4 + data.length);
bytes.writeInt(CSEnum.RELAY);
bytes.writeInt(2); // 转发规则标识
bytes.writeBytes(data);
3 指定组的几个人
bytes.writeInt(4 + 4 + (4 + 4 + 4 * 3) + data.length);
bytes.writeInt(CSEnum.RELAY);
bytes.writeInt(3); // 转发规则标识
bytes.writeInt(id.length);
bytes.writeInt(group);
bytes.writeInt(2); // id 为 2 的用户
bytes.writeInt(3); // id 为 3 的用户
bytes.writeInt(4); // id 为 4 的用户
bytes.writeBytes(data);
4 指定组的几个人(每个人都分组)
bytes.writeInt(4 + 4 + (4 + 4 * 3 * 2) + data.length);
bytes.writeInt(CSEnum.RELAY);
bytes.writeInt(4); // 转发规则标识
bytes.writeInt(id.length);
bytes.writeInt(2); // id 为 2 的用户
bytes.writeInt(group_2); // id 为 2 的用户的组的 id
bytes.writeInt(3); // id 为 3 的用户
bytes.writeInt(group_3); // id 为 3 的用户的组的 id
bytes.writeInt(4); // id 为 4 的用户
bytes.writeInt(group_4); // id 为 4 的用户的组的 id
bytes.writeBytes(data);
5 指定组的所有人
bytes.writeInt(4 + 4 + data.length);
bytes.writeInt(CSEnum.RELAY);
bytes.writeInt(5); // 转发规则标识
bytes.writeInt(group); // 指定的组的 id
bytes.writeBytes(data);
<< 6:服务器转发给指定的用户
bytes.writeInt(4 + 4 + 4 + data.length);
bytes.writeInt(CSEnum.RELAY_BACK);
bytes.writeInt(index);
bytes.writeInt(group);
bytes.writeBytes(data);
>> 7:客户端发送给服务器的日志信息(大家用这里就好了,上面的我写着都好烦啊)
bytes.writeInt(4 + strBytes.length);
bytes.writeInt(CSEnum.SEND);
bytes.writeBytes(strBytes);
<< 7:服务器返回发送成功
bytes.writeInt(4);
bytes.writeInt(CSEnum.SEND);
终于把 Socket 写完了。之所以写这么多,是希望可以帮到需要的人。
Socket 默认侦听 9000 和 9001。9001 是安全策略文件的侦听,会返回一个安全策略 XML,某些应用程序可能会用到,大部分不需要。
还有一个是关于自动打开应用程序的配置的,大家可以去看配置文件,里面有详细的注释,这里已经说很多了,就不说了。
然后上几张截图给大家哈:
来自:http://my.oschina.net/courage/blog/369946