📄 559.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>apue</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center"> ● UNIX网络编程 (BM: clown) </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="15.htm">上一层</a>][<a href="560.htm">下一篇</a>]
<hr><p align="left"><small> <br>
<br>
<br>
发信人: cloudsky (小四), 信区: Security ;32mWWW-POSTm <br>
<br>
标 题: RPC/XDR/NFS系列之----RPC编程初战(1) <br>
<br>
发信站: 武汉白云黄鹤站 (Sun Feb 20 11:48:46 2000) , 站内信件 <br>
<br>
<br>
<br>
★ 启动服务器执行客户机 <br>
<br>
<br>
<br>
[scz@ /home/scz/src]> ./rdictd & <br>
<br>
[1] 553 <br>
<br>
[scz@ /home/scz/src]> ./rdict <br>
<br>
Please input: <br>
<br>
<br>
II <br>
<br>
Dictionary initialized to empty. <br>
<br>
i hellow <br>
<br>
hellow inserted. <br>
<br>
i orld <br>
<br>
orld inserted. <br>
<br>
l hellow <br>
<br>
hellow was found. <br>
<br>
d hellow <br>
<br>
hellow deleted. <br>
<br>
qq <br>
<br>
<br>
Program quits. <br>
<br>
[scz@ /home/scz/src]> kill %1 <br>
<br>
[scz@ /home/scz/src]> <br>
<br>
<br>
<br>
★ 分离服务器和客户机 <br>
<br>
<br>
<br>
修改rdict.c中的 #define RMACHINE "localhost" /* name of remote <br>
<br>
machine */ <br>
<br>
我测试的时候rdictd运行在server上,rdict运行在higgs上,所以改成了 <br>
<br>
<br>
<br>
#define RMACHINE "server" /* name of remote machine */ <br>
<br>
<br>
<br>
<br>
重新编译生成rdict,然后用sftp上传到higgs上,ssh到higgs,chmod +x rdict, <br>
<br>
运 <br>
<br>
行rdict的效果和前面是一样的。至此,一个完整的可以测试使用的真正意义上的 <br>
<br>
RPC <br>
<br>
程序完成了,包括client端和server端。 <br>
<br>
<br>
<br>
★ rpcinfo的使用以及portmap原理简介(重要) <br>
<br>
<br>
<br>
现在让我们从higgs上来看看server <br>
<br>
<br>
<br>
<br>
[scz@ /home/scz/src]> /usr/sbin/rpcinfo <br>
<br>
Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ] <br>
<br>
rpcinfo [ -n portnum ] -t host prognum [ versnum ] <br>
<br>
rpcinfo -p [ host ] <br>
<br>
rpcinfo -b prognum versnum <br>
<br>
rpcinfo -d prognum versnum <br>
<br>
[scz@ /home/scz/src]> /usr/sbin/rpcinfo -p server <br>
<br>
program vers proto port <br>
<br>
100000 2 tcp 111 rpcbind <br>
<br>
100000 2 udp 111 rpcbind <br>
<br>
805898569 1 udp 1029 <br>
<br>
<br>
805898569 1 tcp 1036 <br>
<br>
[scz@ /home/scz/src]> <br>
<br>
<br>
<br>
0x30090949 = 805898569,现在知道rpcinfo的这个program数字是什么了吧, <br>
<br>
就是远程程序号呀。后面的1就是远程程序版本号。tcp表示使用tcp协议作为 <br>
<br>
底层支持协议。回顾rdict.c中的语句: <br>
<br>
<br>
<br>
handle = clnt_create( RMACHINE, RDICTPROG, RDICTVERS, "tcp" ); <br>
<br>
<br>
<br>
第一个参数是远程主机名,第二个参数是远程程序号,第三个参数是远程 <br>
<br>
程序版本号,第四个参数指定底层支持协议。注意到从higgs上运行rpcinfo <br>
<br>
<br>
报告出来的结果,说明rdictd同时支持了tcp和udp,此时如果修改rdict.c <br>
<br>
中的语句: <br>
<br>
<br>
<br>
handle = clnt_create( RMACHINE, RDICTPROG, RDICTVERS, "udp" ); <br>
<br>
<br>
<br>
同样可以达到效果(测试过)。当然,在实际应用中选择tcp还是udp要根据网 <br>
<br>
络状况具体决定。 <br>
<br>
<br>
<br>
rpcinfo报告出来的第四个数据port是什么意思呢,这里简单介绍一下。 <br>
<br>
因为远程程序号总共32bit,超出了端口的16bit范围,所以不能直接在远程 <br>
<br>
程序号和端口号之间建立映射,于是产生了动态端口获得的概念。rpc server <br>
<br>
<br>
通过操作系统获得一个当前空闲的端口号,然后想向端口映射器 <br>
<br>
portmap/rpcbind <br>
<br>
注册这种映射关系。当rpc client需要连接某个rpc server的时候,前者只知道 <br>
<br>
远程程序号和远程程序版本号,于是它向目标主机的知名端口111提供的服务 <br>
<br>
查询拥有相应远程程序号和远程程序版本号的rpc server当前所注册使用的端口 <br>
<br>
号,由portmap/rpcbind向rpc client提供这个端口值,当rpc client获得 <br>
<br>
rpc server所使用的端口值后就可以直接与rpc server通信了。所以,如果上面 <br>
<br>
rdictd二次启动后用rpcinfo查看,会发现port值改变。从上面简单介绍的理论 <br>
<br>
中应该明白,rpc server必须向portmap注册,所以如果: <br>
<br>
<br>
<br>
[root@ /home/scz/src]> /etc/rc.d/init.d/portmap status <br>
<br>
<br>
portmap (pid 539) is running... <br>
<br>
[root@ /home/scz/src]> /etc/rc.d/init.d/portmap stop <br>
<br>
Stopping portmap services: <br>
<br>
[ OK ] <br>
<br>
[root@ /home/scz/src]> <br>
<br>
<br>
<br>
[scz@ /home/scz/src]> /usr/sbin/rpcinfo -p localhost <br>
<br>
rpcinfo: can't contact portmapper: RPC: Remote system error - Connection <br>
<br>
refused <br>
<br>
[scz@ /home/scz/src]> ./rdictd <br>
<br>
Cannot register service: RPC: Unable to receive; errno = Connection <br>
<br>
<br>
refused <br>
<br>
<br>
<br>
unable to register (RDICTPROG, RDICTVERS, udp). <br>
<br>
[scz@ /home/scz/src]> <br>
<br>
<br>
<br>
现在你是否对rpc程序执行中的错误提示有了进一步了解呢。如果答案肯定, <br>
<br>
那我很高兴。注意这里,如果当初没有修改过rdict_svc.c,最后的错误提示 <br>
<br>
会让你非常恼火,因为没有回车换行。 <br>
<br>
<br>
<br>
通过netconf设置portmap服务在系统启动的时候就开始。如果要临时测试, <br>
<br>
就是上面那个办法。有的系统是在/etc/inetd.conf中提供rpcbind服务, <br>
<br>
<br>
也是111端口,必须注意到这一点。 <br>
<br>
<br>
<br>
我这里居然没有rpcinfo的man手册,活见鬼,所以那些命令行选项什么意思 <br>
<br>
我也不清楚,只能挑我大概知道的给出例子,如果你明白就赶快贴出来好了, <br>
<br>
solaris下应该有相应的man手册吧。 <br>
<br>
<br>
<br>
下面我们来看看rpcinfo的其他命令行选项: <br>
<br>
<br>
<br>
[scz@ /home/scz/src]> hostname <br>
<br>
higgs.*.*.* <br>
<br>
[scz@ /home/scz/src]> /usr/sbin/rpcinfo -b 805898569 1 <br>
<br>
<br>
192.168.67.108 server.*.*.* <br>
<br>
^C <br>
<br>
[scz@ /home/scz/src]> <br>
<br>
<br>
<br>
-b选项似乎是在局域网上探测指定rpc server的存在??? <br>
<br>
<br>
<br>
[root@ /home/scz/src]> rpcinfo -d 100000 2 <br>
<br>
[root@ /home/scz/src]> rpcinfo -p localhost <br>
<br>
No remote programs registered. <br>
<br>
[root@ /home/scz/src]> /etc/rc.d/init.d/portmap status <br>
<br>
portmap (pid 740) is running... <br>
<br>
<br>
[root@ /home/scz/src]> ./rdictd & <br>
<br>
[root@ /home/scz/src]> jobs <br>
<br>
[1]+ Running ./rdictd & <br>
<br>
[root@ /home/scz/src]> rpcinfo -p localhost <br>
<br>
program vers proto port <br>
<br>
805898569 1 udp 966 <br>
<br>
805898569 1 tcp 968 <br>
<br>
[root@ /home/scz/src]> kill %1 <br>
<br>
[1]+ Terminated ./rdictd <br>
<br>
[root@ /home/scz/src]> jobs <br>
<br>
[root@ /home/scz/src]> rpcinfo -p localhost <br>
<br>
<br>
program vers proto port <br>
<br>
805898569 1 udp 966 <br>
<br>
805898569 1 tcp 968 <br>
<br>
[root@ /home/scz/src]> rpcinfo -d 805898569 1 <br>
<br>
[root@ /home/scz/src]> rpcinfo -p localhost <br>
<br>
No remote programs registered. <br>
<br>
[root@ /home/scz/src]> <br>
<br>
<br>
<br>
-d选项看来是反注册用的。注意到rdictd虽然被杀,但动态端口注册信息依 <br>
<br>
旧存在,需要额外地用rpcinfo -d反注册一下,同样先反注册并不会导致 <br>
<br>
rdictd终止,这两者没有捆绑。rpcbind被反注册掉不影响什么,至少目前 <br>
<br>
<br>
测试结果如此,也许rpcbind本身注册一次仅仅是保持某种一致性,因为它 <br>
<br>
使用的是固定的周知端口111,根本不用注册的。 <br>
<br>
<br>
<br>
[scz@ /home/scz/src]> ./rdictd & <br>
<br>
[1] 798 <br>
<br>
[scz@ /home/scz/src]> rpcinfo -p localhost <br>
<br>
program vers proto port <br>
<br>
805898569 1 udp 1043 <br>
<br>
805898569 1 tcp 1054 <br>
<br>
[scz@ /home/scz/src]> <br>
<br>
<br>
<br>
<br>
[scz@ /home/scz/src]> hostname <br>
<br>
higgs.*.*.* <br>
<br>
[scz@ /home/scz/src]> /usr/sbin/rpcinfo -t server 805898569 <br>
<br>
program 805898569 version 1 ready and waiting <br>
<br>
[scz@ /home/scz/src]> /usr/sbin/rpcinfo -n 1043 -u server 805898569 1 <br>
<br>
program 805898569 version 1 ready and waiting <br>
<br>
[scz@ /home/scz/src]> <br>
<br>
<br>
<br>
简单的小结: <br>
<br>
<br>
<br>
. 构建一个解决问题的常规程序。 <br>
<br>
<br>
. 根据某种原则划分开,其中一部分是准备迁移到远程主机上作为远 <br>
<br>
程过程调用的。 <br>
<br>
. 编写rpcgen规格说明文件 <br>
<br>
. 运行rpcgen <br>
<br>
. 为rpc client和rpc server编写各自的stub接口例程 <br>
<br>
. 编译连接rpc client和rpc server <br>
<br>
<br>
<br>
rpcgen虽然解决了很多问题,但并非一定要使用rpcgen进行rpc编程。 <br>
<br>
尤其当一个rpc server是另外一个rpc server的rpc client的时候, <br>
<br>
rpcgen的局限性就暴露出来了。 <br>
<br>
<br>
<br>
后记: <br>
<br>
<br>
<br>
正好要做点和RPC/NFS有关的协议分析,于是就 <br>
<br>
把上面那本书重新翻出来,照猫画老虎地先测试 <br>
<br>
一个完整的RPC程序,给自己一点信心也给大家 <br>
<br>
一个免除重复劳动的便宜捡。有任何技术性问题, <br>
<br>
可以< mailto: cloudsky@263.net >,反正我什么 <br>
<br>
都不知道,你要教训我正好嘛,:-) <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="15.htm">上一层</a>][<a href="560.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -