pedrpc.py 是sulley中的一份代码,用于实现函数的远程调用。即客户端调用函数(但是客户端并没有该函数),在服务器端执行程序,然后返回结果。
远程调用可行的两个条件:python中__getattr__的默认调用以及exec的创建代码字符串的功能;
__getattr__():在Client端,当一个没有被定义的属性或方法被访问时,该函数被默认调用;该函数只传递所需要的属性(如函数名)不传递参数,因此要扩展。将函数的参数采用lambda构造表达式,返回表达式的值。
exec() :在Sever端,能将接收到的函数名动态的创建为代码字符串。
通信协议
通信方式:TCP套接字;
数据的组织形式:LengthOfData(4B) + Data。4字节的长度域,随后才是数据。
Client:
1. 访问函数methodname,未能在“usual places”找到函数的定义,则系统默认调用__getattr__(),从而触发远程调用;
2. 若要访问的函数为__nonzero__()则直接返回1?过滤掉私有成员函数(函数名以’__’开头);采用cPickle.dumps将元组“(函数名,参数) ”序列化,按照约定的“协议”发送至目的端。
Server:
1. 接受客户端请求;
2. 接收长度(recv(4)),接收数据,将接收到的数据反序列化,获取元组(函数名,参数);
3. 通过exec将接收到的函数名(字符串形式)创建为代码字符串,结合接收到的参数,运行得出结果;
4. 将结果发送至client端。
综述:
1. 发送的数据经过cPickle.dumps序列化;
2. 发送的数据形式:数据长度(4B)+数据;
3. 源端发送数据长度,以及序列化后的数据;
4. 目的端接收数据长度,并获取对应的长度的数据,再反序列化(cPickle.loads),从而得到原始(序列化之前的)对象;
问题:
1. 长度为什么要以小端(<)发送? (网络字节顺序)
小端是windows的字节顺序,用大端也完全可以,只要两边一致
2. 函数名的过滤中,”__nonzero__”不懂?是一个函数的话,为什么这个函数要特殊考虑?
这个是内置函数,可以返回一个对象bool条件测试的值,例如if x会调用x的nonzero方法
3. 调用__getattr__()的条件:” Called when an attribute lookup has not found the attribute in the usual places”中,“usual places”不懂。
Usual places是指普通的对象都有一个方法表,方法都保存在这个地方。