<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[什么是 RPC 及其Rpc编写的学习URL地址]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Sun, 19 Dec 2010 13:10:19 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	关于“RPC语言”<br/>RPC语言也是一种专门的编程语言，当然这里我们不需要知道太多，只需要能看懂下面这种基本结构就行了：<br/>program TESTPROG &#123;<br/>&nbsp;&nbsp; version VERSION &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; string TEST(string) = 1;<br/>&nbsp;&nbsp; &#125; = 1;<br/>&#125; = 87654321; <br/>这里TESTPROG和VERSION是两个变量，用于标识一个单独的RPC接口。这被RPC服务程序，比如portmap用到，我们可以不用关心，变量名字也是随便取的。但取值要在你的系统中是唯一的。<br/>“string TEST(string) = 1;”这一行说明有两个函数test_VERSION和test_VERSION_svc，这里由于VERSION变量为1，所以函数名为test_1和 test_1_svc，这两个函数用于在服务器端和客户端实现调用，即：<br/>在客户端调用test_1函数，服务器端调用test_1_svc函数处理并返回。<br/>函数的类型是string，RPC语言中string即C里面的一个字符串。所以上述函数有一个字符串作为参数传递，同时要返回字符串。即：<br/>char ** test_1(char **argp, CLIENT *clnt) 和 char **test_1_svc(char **argp, struct svc_req *rqstp)<br/><br/>同理，如果声明是这样的：<br/>program RDICTPROG&nbsp;&nbsp;/* name of remote program ( not used ) */<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;version RDICTVERS&nbsp;&nbsp;/* declaration of version ( see below ) */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int INITW ( void )&nbsp;&nbsp;&nbsp;&nbsp; = 1;&nbsp;&nbsp;/* first procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int INSERTW ( string ) = 2;&nbsp;&nbsp;/* second procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int DELETEW ( string ) = 3;&nbsp;&nbsp;/* third procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int LOOKUPW ( string ) = 4;&nbsp;&nbsp;/* fourth procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; = 1;&nbsp;&nbsp;/* definition of the program version */<br/>&#125; = 0x30090949;&nbsp;&nbsp;/* remote program number ( must be unique ) */ <br/>则说明这个RPC中有四个函数可用，即客户端可以调用initw_1、insertw_1、deletew_1、lookupw_1四个函数来向服务端发送消息，服务端可以用initw_1_svc、insertw_1_svc、deletew_1_svc、lookupw_1_svc四个函数来处理请求并返回结果。<br/><br/>原任务<br/>假设现在有这样一个程序，源代码如下：<br/>/* dict.c -- main, initw, nextin, insertw, deletew, lookupw */<br/>#include &lt;stdio.h&gt;<br/>#include &lt;string.h&gt;<br/>#include &lt;stdlib.h&gt;<br/>#include &lt;ctype.h&gt;<br/>#define MAXWORD 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* maximum length of a command or word */<br/>#define DICTSIZ 100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* maximum number of entries in dictionary. */<br/>char dict[DICTSIZ][MAXWORD + 1];&nbsp;&nbsp;&nbsp;&nbsp;/* storage for a dictionary of words */<br/>int nwords = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* number of words in the dictionary */<br/>/* 函数原型 */<br/>int nextin(char *cmd, char *word);<br/>int initw(void);<br/>int insertw(const char *word);<br/>int deletew(const char *word);<br/>int lookupw(const char *word);<br/>/* ------------------------------------------------------------------<br/>* main -- insert, delete, or lookup words in a dictionary as specified<br/>* ------------------------------------------------------------------ */<br/>int main(int argc, char *argv[])<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;char word[MAXWORD + 1];&nbsp;&nbsp;&nbsp;&nbsp;/* space to hold word from input line */<br/>&nbsp;&nbsp;&nbsp;&nbsp;char cmd;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int wordlen;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* length of input word */<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Please input:&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (1) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;wordlen = nextin(&amp;cmd, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (wordlen &lt; 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;switch (cmd) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;I&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 初始化 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initw();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Dictionary initialized to empty.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;i&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 插入 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertw(word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s inserted.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;d&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 删除 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (deletew(word)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s deleted.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s not found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;l&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 查询 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (lookupw(word)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s was found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s was not found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;q&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 退出 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Program quits.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 非法输入 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;command %c invalid.&#92;n&quot;, cmd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of switch */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of main */<br/><br/>/* ------------------------------------------------------------------<br/>* nextin -- read a command and(possibly) a word from the next input line<br/>* ------------------------------------------------------------------ */<br/>int nextin(char *cmd, char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i, ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == EOF) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;*cmd = (char) ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == EOF) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == &#039;&#92;n&#039;) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;i = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (!isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (++i &gt; MAXWORD) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;error: word too long.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;*word++ = ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;*word = &#039;&#92;0&#039;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 原来的代码这里有问题 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return i;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of nextin */<br/><br/>/* ------------------------------------------------------------------<br/>* initw -- initialize the dictionary to contain no words at all<br/>* ------------------------------------------------------------------ */<br/>int initw(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;nwords = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of initw */<br/><br/>/* ------------------------------------------------------------------<br/>* insertw -- insert a word in the dictionary<br/>* ------------------------------------------------------------------ */<br/>int insertw(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;strcpy(dict[nwords], word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nwords++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (nwords);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of insertw */<br/><br/>/* ------------------------------------------------------------------<br/>* deletew -- delete a word from the dictionary<br/>* ------------------------------------------------------------------ */<br/>int deletew(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; nwords; i++) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (strcmp(word, dict[i]) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nwords--;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(dict[i], dict[nwords]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of for */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of deletew */<br/><br/>/* ------------------------------------------------------------------<br/>* lookupw -- look up a word in the dictionary<br/>* ------------------------------------------------------------------ */<br/>int lookupw(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; nwords; i++) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (strcmp(word, dict[i]) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of for */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of lookupw */<br/> <br/>这是一个简单的字典程序，即程序运行起来以后维护着一个字典库，用户可以向里面添加词语，也可以查询或删除词语。<br/>当然，这个程序只能在同一台主机上运行。程序整个运行过程中，只需要完成如下几个步骤：<br/>A、接受用户输入；<br/>B、分析用户输入决定是否进行下面的步骤：<br/>&nbsp;&nbsp;&nbsp;&nbsp;1、初始化数据库；<br/>&nbsp;&nbsp;&nbsp;&nbsp;2、向数据库添加词语；<br/>&nbsp;&nbsp;&nbsp;&nbsp;3、查询或删除词语<br/><br/>任务分解<br/>大家可以想到，对于一个大型系统，比如需要有很多人维护这个系统的数据。象上面这样独立的程序就不适用了，需要做成分布式系统：<br/>即一个服务器维护着数据库，任何客户端都可以接受用户请求，客户端分析用户命令后提交给服务器去处理。<br/>所以我们可能会把程序分成两部分：<br/>客户端：接受用户输入，并判断用户输入内容的正确性，向服务器提交数据，等服务器返回消息<br/>服务器端：维护数据，接受客户端命令并执行后返回结果。<br/>所以我们把上面这个程序分解成下面两部分：<br/>/* dict1.c -- main, nextin */<br/>#include &lt;stdio.h&gt;<br/>#include &lt;stdlib.h&gt;<br/>#define MAXWORD 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* maximum length of a command or word */<br/>/* ------------------------------------------------------------------<br/>* main -- insert, delete, or lookup words in a dictionary as specified<br/>* ------------------------------------------------------------------ */<br/>int main(int argc, char *argv[])<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;char word[MAXWORD + 1];&nbsp;&nbsp;&nbsp;&nbsp;/* space to hold word from input line */<br/>&nbsp;&nbsp;&nbsp;&nbsp;char cmd;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int wordlen;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* length of input word */<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Please input:&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (1) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;wordlen = nextin(&amp;cmd, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (wordlen &lt; 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;switch (cmd) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;I&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 初始化 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initw();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Dictionary initialized to empty.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;i&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 插入 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertw(word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s inserted.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;d&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 删除 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (deletew(word)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s deleted.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s not found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;l&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 查询 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (lookupw(word)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s was found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s was not found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;q&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 退出 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Program quits.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 非法输入 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;command %c invalid.&#92;n&quot;, cmd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of switch */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of main */<br/><br/>/* ------------------------------------------------------------------<br/>* nextin -- read a command and(possibly) a word from the next input line<br/>* ------------------------------------------------------------------ */<br/>int nextin(char *cmd, char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i, ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == EOF) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;*cmd = (char) ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == EOF) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == &#039;&#92;n&#039;) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;i = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (!isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (++i &gt; MAXWORD) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;error: word too long.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;*word++ = ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;*word = &#039;&#92;0&#039;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return i;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of nextin */<br/> <br/>和<br/>/* dict2.c -- initw, insertw, deletew, lookupw */<br/>#include &lt;string.h&gt;<br/>#define MAXWORD 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* maximum length of a command or word */<br/>#define DICTSIZ 100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* maximum number of entries in dictionary. */<br/>char dict[DICTSIZ][MAXWORD + 1];&nbsp;&nbsp;&nbsp;&nbsp;/* storage for a dictionary of words */<br/>int nwords = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* number of words in the dictionary */<br/>/* ------------------------------------------------------------------<br/>* initw -- initialize the dictionary to contain no words at all<br/>* ------------------------------------------------------------------ */<br/>int initw(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;nwords = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of initw */<br/><br/>/* ------------------------------------------------------------------<br/>* insertw -- insert a word in the dictionary<br/>* ------------------------------------------------------------------ */<br/>int insertw(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;strcpy(dict[nwords], word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nwords++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (nwords);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of insertw */<br/><br/>/* ------------------------------------------------------------------<br/>* deletew -- delete a word from the dictionary<br/>* ------------------------------------------------------------------ */<br/>int deletew(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; nwords; i++) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (strcmp(word, dict[i]) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nwords--;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(dict[i], dict[nwords]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of for */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of deletew */<br/><br/>/* ------------------------------------------------------------------<br/>* lookupw -- look up a word in the dictionary<br/>* ------------------------------------------------------------------ */<br/>int lookupw(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; nwords; i++) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (strcmp(word, dict[i]) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of for */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of lookupw */<br/> <br/>这两部分代码只是在功能上实现了分离，显然实现通讯的部分还没有，下面我们利用RPC来快速实现通讯。<br/><br/>利用RPC实现分布式系统<br/>首先，建立一个RPC源文件，源代码rdict.x如下：<br/>/* rdict.x */<br/>/* RPC declarations for dictionary program */<br/>const MAXWORD = 10;&nbsp;&nbsp; /* maximum length of a command or word */<br/>const DICTSIZ = 3;&nbsp;&nbsp;/* number of entries in dictionary */<br/>struct example&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* unused structure declared here to */<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;exfield1;&nbsp;&nbsp;/* illustrate how rpcgen builds XDR */<br/>&nbsp;&nbsp;&nbsp;&nbsp;char exfield2;&nbsp;&nbsp;/* routines to convert structures */<br/>&#125;;<br/>/* ------------------------------------------------------------------<br/>* RDICTPROG -- remote program that provides insert, delete, and lookup<br/>* ------------------------------------------------------------------ */<br/>program RDICTPROG&nbsp;&nbsp;/* name of remote program ( not used ) */<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;version RDICTVERS&nbsp;&nbsp;/* declaration of version ( see below ) */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int INITW ( void )&nbsp;&nbsp;&nbsp;&nbsp; = 1;&nbsp;&nbsp;/* first procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int INSERTW ( string ) = 2;&nbsp;&nbsp;/* second procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int DELETEW ( string ) = 3;&nbsp;&nbsp;/* third procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int LOOKUPW ( string ) = 4;&nbsp;&nbsp;/* fourth procedure in this program */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; = 1;&nbsp;&nbsp;/* definition of the program version */<br/>&#125; = 0x30090949;&nbsp;&nbsp;/* remote program number ( must be unique ) */<br/> <br/>然后用下列命令产生服务器端函数rdict_srv_func.c：<br/>rpcgen -Ss -o rdict_srv_func.c rdict.x <br/>然后用下列命令产生客户端程序rdict_client.c：<br/>rpcgen -Sc -o rdict_client.c rdict.x <br/>/************关于本文档********************************************<br/>*filename: 我是这样学习Linux下C语言编程的-利用RPC快速实现分布式系统<br/>*purpose: 说明如何利用RPC快速进行客户端-服务器端C-S结构编程<br/>*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)<br/>Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言<br/>*date time:2007-02-27 19:20<br/>*Note: 任何人可以任意复制代码并运用这些文档，当然包括你的商业用途<br/>* 但请遵循GPL<br/>*Thanks to:<br/>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ubuntu 本程序在Ubuntu 6.10系统上测试完全正常<br/>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Google.com 我通过google搜索并参考了RPC编程相关的许多文章<br/>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网络安全焦点(www.xfocus.net) 我主要借鉴了此文 http://www.xfocus.net/articles/200009/10.html<br/>*Hope:希望越来越多的人贡献自己的力量，为科学技术发展出力<br/>* 科技站在巨人的肩膀上进步更快！感谢有开源前辈的贡献！<br/>*********************************************************************/<br/>然后用下列命令产生Makefile：<br/> rpcgen -Sm rdict.x &gt; Makefile<br/> <br/>Makefile文件原内容如下：<br/># This is a template Makefile generated by rpcgen<br/><br/># Parameters<br/><br/>CLIENT = rdict_client<br/>SERVER = rdict_server<br/><br/>SOURCES_CLNT.c = <br/>SOURCES_CLNT.h = <br/>SOURCES_SVC.c = <br/>SOURCES_SVC.h = <br/>SOURCES.x = rdict.x<br/><br/>TARGETS_SVC.c = rdict_svc.c&nbsp;&nbsp; rdict_xdr.c <br/>TARGETS_CLNT.c = rdict_clnt.c&nbsp;&nbsp; rdict_xdr.c <br/>TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)<br/>OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)<br/># Compiler flags <br/><br/>CFLAGS += -g <br/>LDLIBS += -lnsl<br/>RPCGENFLAGS = <br/><br/># Targets <br/><br/>all : $(CLIENT) $(SERVER)<br/><br/>$(TARGETS) : $(SOURCES.x) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rpcgen $(RPCGENFLAGS) $(SOURCES.x)<br/><br/>$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c) <br/><br/>$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c) <br/><br/>$(CLIENT) : $(OBJECTS_CLNT) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS) <br/><br/>$(SERVER) : $(OBJECTS_SVC) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)<br/><br/> clean:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)<br/> <br/>动手修改Makefile，修改后内容如下：<br/># This is a template Makefile generated by rpcgen<br/><br/># Parameters<br/><br/>CLIENT = rdict_client<br/>SERVER = rdict_server<br/><br/>SOURCES_CLNT.c = <br/>SOURCES_CLNT.h = <br/>SOURCES_SVC.c = <br/>SOURCES_SVC.h = <br/>SOURCES.x = rdict.x<br/><br/>TARGETS_SVC.c = rdict_svc.c&nbsp;&nbsp; rdict_xdr.c rdict_srv_func.c<br/>TARGETS_CLNT.c = rdict_clnt.c&nbsp;&nbsp; rdict_xdr.c rdict_client.c<br/>TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c<br/><br/>OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)<br/>OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)<br/># Compiler flags <br/><br/>CFLAGS += -g <br/>LDLIBS += -lnsl<br/>RPCGENFLAGS = <br/><br/># Targets <br/><br/>all : $(CLIENT) $(SERVER)<br/><br/>$(TARGETS) : $(SOURCES.x) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rpcgen $(RPCGENFLAGS) $(SOURCES.x)<br/><br/>$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c) <br/><br/>$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c) <br/><br/>$(CLIENT) : $(OBJECTS_CLNT) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS) <br/><br/>$(SERVER) : $(OBJECTS_SVC) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)<br/><br/>clean:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER) *~<br/> <br/>修改客户端源代码rdict_client.c，把接受用户输入并分析用户输入内容的部分加到程序中来。修改后的代码为：<br/>/*<br/> * This is sample code generated by rpcgen.<br/> * These are only templates and you can use them<br/> * as a guideline for developing your own functions.<br/> */<br/><br/>#include &quot;rdict.h&quot;<br/><br/>/* ------------------------------------------------------------------<br/>* nextin -- read a command and(possibly) a word from the next input line<br/>* ------------------------------------------------------------------ */<br/>int nextin(char *cmd, char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i, ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == EOF) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;*cmd = (char) ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == EOF) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (ch == &#039;&#92;n&#039;) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;i = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (!isspace(ch)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (++i &gt; MAXWORD) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;error: word too long.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;*word++ = ch;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ch = getc(stdin);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/>&nbsp;&nbsp;&nbsp;&nbsp;*word = &#039;&#92;0&#039;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return i;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of nextin */<br/><br/>void rdictprog_1(char *host)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;CLIENT *clnt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int *result_1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;char *initw_1_arg;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int *result_2;<br/>&nbsp;&nbsp;&nbsp;&nbsp;char *insertw_1_arg;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int *result_3;<br/>&nbsp;&nbsp;&nbsp;&nbsp;char *deletew_1_arg;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int *result_4;<br/>&nbsp;&nbsp;&nbsp;&nbsp;char *lookupw_1_arg;<br/><br/>#ifndef&nbsp;&nbsp;&nbsp;&nbsp;DEBUG<br/>&nbsp;&nbsp;&nbsp;&nbsp;clnt = clnt_create(host, RDICTPROG, RDICTVERS, &quot;udp&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (clnt == NULL) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;clnt_pcreateerror(host);<br/>&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>#endif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* DEBUG */<br/>&nbsp;&nbsp;&nbsp;&nbsp;char word[MAXWORD + 1];&nbsp;&nbsp;&nbsp;&nbsp;/* space to hold word from input line */<br/>&nbsp;&nbsp;&nbsp;&nbsp;char cmd;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int wordlen;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* length of input word */<br/>&nbsp;&nbsp;&nbsp;&nbsp;while (1) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;&#92;nPlease input:&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;wordlen = nextin(&amp;cmd, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (wordlen &lt; 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;/* printf(&quot;&#92;nYour cmd is:%c, your word is:%s&#92;n&quot;, cmd, word); */<br/>&nbsp;&nbsp;&nbsp;&nbsp;switch (cmd) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;I&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 初始化 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_1 = initw_1((void *) &amp;initw_1_arg, clnt);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* printf(&quot;&#92;nYour result is:%d&#92;n&quot;, *result_1); */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (result_1 == (int *) NULL)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clnt_perror(clnt, &quot;call failed&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(*result_1 ==0) printf(&quot;Dictionary initialized to empty.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else printf(&quot;Dictionary have already initialized.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;i&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 插入 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertw_1_arg = word;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_2 = insertw_1(&amp;insertw_1_arg, clnt);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* printf(&quot;&#92;nYour result is:%d, your string is:%s(%d)&#92;n&quot;, *result_2, insertw_1_arg, strlen(insertw_1_arg)); */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (result_2 == (int *) NULL)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clnt_perror(clnt, &quot;call failed&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s inserted.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;d&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 删除 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deletew_1_arg = word;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_3 = deletew_1(&amp;deletew_1_arg, clnt);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* printf(&quot;&#92;nYour result is:%d, your string is:%s(%d)&#92;n&quot;, *result_3, deletew_1_arg, strlen(deletew_1_arg)); */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (result_3 == (int *) NULL)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clnt_perror(clnt, &quot;call failed&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s deleted.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;l&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 查询 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lookupw_1_arg = word;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result_4 = lookupw_1(&amp;lookupw_1_arg, clnt);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* printf(&quot;&#92;nYour result is:%d, your string is:%s(%d)&#92;n&quot;, *result_4, lookupw_1_arg, strlen(lookupw_1_arg)); */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (result_4 == (int *) NULL)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clnt_perror(clnt, &quot;call failed&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(*result_4 ==0) printf(&quot;%s found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else printf(&quot;%s not found.&#92;n&quot;, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case &#039;q&#039;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 退出 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Program quits.&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* 非法输入 */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Command %c(%s) invalid.&#92;n&quot;, cmd, word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of switch */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of while */<br/><br/>#ifndef&nbsp;&nbsp;&nbsp;&nbsp;DEBUG<br/>&nbsp;&nbsp;&nbsp;&nbsp;clnt_destroy(clnt);<br/>#endif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* DEBUG */<br/>&#125;<br/><br/><br/>int main(int argc, char *argv[])<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;char *host;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (argc &lt; 2) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;usage: %s server_host&#92;n&quot;, argv[0]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;host = argv[1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;rdictprog_1(host);<br/>&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&#125;<br/> <br/>同时修改服务器端代码rdict_srv_func.c，修改后内容为：<br/>/*<br/> * This is sample code generated by rpcgen.<br/> * These are only templates and you can use them<br/> * as a guideline for developing your own functions.<br/> */<br/><br/>#include &quot;rdict.h&quot;<br/><br/>char dict[DICTSIZ][MAXWORD + 1];&nbsp;&nbsp;&nbsp;&nbsp;/* storage for a dictionary of words */<br/>int nwords = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* number of words in the dictionary */<br/>char init_bool = 0;<br/><br/>int initw(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(init_bool) return 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;nwords = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;init_bool = 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of initw */<br/><br/>/* ------------------------------------------------------------------<br/>* insertw -- insert a word in the dictionary<br/>* ------------------------------------------------------------------ */<br/>int insertw(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;strcpy(dict[nwords%DICTSIZ], word);<br/>&nbsp;&nbsp;&nbsp;&nbsp;nwords++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (nwords);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of insertw */<br/><br/>/* ------------------------------------------------------------------<br/>* deletew -- delete a word from the dictionary<br/>* ------------------------------------------------------------------ */<br/>int deletew(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; nwords; i++) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (strcmp(word, dict[i]) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nwords--;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(dict[i], dict[nwords]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of for */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (0);<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of deletew */<br/><br/>/* ------------------------------------------------------------------<br/>* lookupw -- look up a word in the dictionary<br/>* ------------------------------------------------------------------ */<br/>int lookupw(const char *word)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; nwords; i++) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (strcmp(word, dict[i]) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of for */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* end of lookupw */<br/><br/>int *initw_1_svc(void *argp, struct svc_req *rqstp)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;static int result;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/*<br/>&nbsp;&nbsp;&nbsp;&nbsp; * insert server code here<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;result = initw();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return &amp;result;<br/>&#125;<br/><br/>int *insertw_1_svc(char **argp, struct svc_req *rqstp)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;static int result;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/*<br/>&nbsp;&nbsp;&nbsp;&nbsp; * insert server code here<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/>&nbsp;&nbsp;&nbsp;&nbsp;result = insertw(*argp);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return &amp;result;<br/>&#125;<br/><br/>int *deletew_1_svc(char **argp, struct svc_req *rqstp)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;static int result;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/*<br/>&nbsp;&nbsp;&nbsp;&nbsp; * insert server code here<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;result = deletew(*argp);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return &amp;result;<br/>&#125;<br/><br/>int *lookupw_1_svc(char **argp, struct svc_req *rqstp)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;static int result;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/*<br/>&nbsp;&nbsp;&nbsp;&nbsp; * insert server code here<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;result = lookupw(*argp);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return &amp;result;<br/>&#125;<br/> <br/>至此，程序做好了。输入一个make命令就可以生成test_server和test_client这两个可执行程序了。<br/>在一台机器上运行./test_server程序，在另外的客户机上运行./test_client server_ip就可以了。这里server_ip是运行着test_server程序的主机的IP地址。 <br/><br/><br/><br/>http://blog.chinaunix.net/u/21675/showart.php?id=308008<br/>http://blog.chinaunix.net/u2/66973/showart_1071175.html<br/><br/>RPC example:<br/>http://blog.chinaunix.net/u3/102500/showart_2128311.html<br/>http://blog.chinaunix.net/u1/37472/showart_726114.html<br/>http://blog.chinaunix.net/u1/37472/showart_726114.html<br/>http://blog.chinaunix.net/u3/119073/showart_2342954.html<br/>http://blog.chinaunix.net/u3/94300/showart_1900094.html<br/>linux下rpc的多线程实现<br/> <br/> <br/> <br/>solaris下rpc可以通过rpcgen -A让服务器根据处理新用户请求的需要自动创建线程。但是linux没有实现这个功能，原因据说是会产生非线程安全的代码。<br/><br/>本文给出了一种实现上述功能的方法。参考了http://ftp.traduc.org/doc-vf/gazette-linux/gazette-us/2004/103/103D.html<br/>和http://linux.ittoolbox.com/groups/technical-functional/redhat-l/multithreaded-rpc-servers-for-linux-482547<br/><br/>下面以unp2e2上的square3为例子，通过修改部分代码来实现<br/><br/>文件square.x<br/><br/>struct square_in&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;long arg1;<br/>&#125;;<br/>struct square_out&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;long res1;<br/>&#125;;<br/>program SQUARE_PROG&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;version SQARE_VERS&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;square_out SQUAREPROC(square_in) = 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; = 2;<br/><br/>&#125; = 0x31230000<br/> <br/><br/>接着执行：<br/>rpcgen -aM square.x<br/>该指令产生了文件：<br/>square_clnt.c&nbsp;&nbsp;square_server.c&nbsp;&nbsp;Makefile.square&nbsp;&nbsp;square_client.c&nbsp;&nbsp;square.h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; square_svc.c&nbsp;&nbsp; square_xdr.c<br/><br/>着重要修改的是square_svc.c文件：<br/><br/><br/>/* 被修改过的<br/> * Please do not edit this file.<br/> * It was generated using rpcgen.<br/> */<br/><br/>#include &quot;square.h&quot;<br/>#include &lt;stdio.h&gt;<br/>#include &lt;stdlib.h&gt;<br/>#include &lt;rpc/pmap_clnt.h&gt;<br/>#include &lt;string.h&gt;<br/>#include &lt;memory.h&gt;<br/>#include &lt;sys/socket.h&gt;<br/>#include &lt;netinet/in.h&gt;<br/><br/>#ifndef SIG_PF<br/>#define SIG_PF void(*)(int)<br/>#endif<br/><br/>pthread_t p_thread;<br/>pthread_attr_t attr;<br/><br/>//static void<br/>//square_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)<br/>void *<br/>serv_request(void *data)<br/>&#123;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;struct thr_data &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct svc_req *rqstp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SVCXPRT&nbsp;&nbsp;&nbsp;&nbsp;*transp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; *ptr_data;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;union &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;square_in squareproc_2_arg;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; argument;<br/>&nbsp;&nbsp;&nbsp;&nbsp;union &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;square_out squareproc_2_res;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; result;<br/>&nbsp;&nbsp;&nbsp;&nbsp;bool_t retval;<br/>&nbsp;&nbsp;&nbsp;&nbsp;xdrproc_t _xdr_argument, _xdr_result;<br/>&nbsp;&nbsp;&nbsp;&nbsp;bool_t (*local)(char *, void *, struct svc_req *);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;ptr_data = (struct thr_data *)data;<br/>&nbsp;&nbsp;&nbsp;&nbsp;struct svc_req *rqstp = ptr_data-&gt;rqstp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;register SVCXPRT *transp = ptr_data-&gt;transp;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;switch (rqstp-&gt;rq_proc) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case NULLPROC:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(void) svc_sendreply (transp, (xdrproc_t) xdr_void,(char *)NULL);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;case SQUAREPROC:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_xdr_argument = (xdrproc_t) xdr_square_in;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_xdr_result = (xdrproc_t) xdr_square_out;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local = (bool_t (*) (char *, void *, struct svc_req *))squareproc_2_svc;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;default:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svcerr_noproc (transp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;memset ((char *)&amp;argument, 0, sizeof (argument));<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_getargs (transp, (xdrproc_t) _xdr_argument,(caddr_t) &amp;argument)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svcerr_decode (transp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;retval = (bool_t) (*local)((char *)&amp;argument, (void *)&amp;result, rqstp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (retval &gt; 0 &amp;&amp; !svc_sendreply(transp, (xdrproc_t), (char *)&amp;result)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svcerr_systemerr (transp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument,(caddr_t) &amp;argument)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to free arguments&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!square_prog_2_freeresult (transp, _xdr_result,(caddr_t) &amp;result))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to free results&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&#125;<br/><br/>//new square_prog_2<br/>static void<br/>square_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;struct data_str&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct svc_req *rqstp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SVCXPRT *transp;<br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; *data_ptr=(struct data_str*)malloc(sizeof(struct));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;data_ptr-&gt;rqstp = rqstp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;data_ptr-&gt;transp = transp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;pthread_attr_setdetachstate(&amp;attr,PTHREAD_CREATE_DETACHED); <br/>&nbsp;&nbsp;&nbsp;&nbsp;pthread_create(&amp;p_thread,&amp;attr,serv_request,(void*)data_ptr);<br/>&#125;<br/><br/>int<br/>main (int argc, char **argv)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;register SVCXPRT *transp;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;pmap_unset (SQUARE_PROG, SQARE_VERS);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;transp = svcudp_create(RPC_ANYSOCK);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (transp == NULL) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;cannot create udp service.&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_register(transp, SQUARE_PROG, SQARE_VERS, square_prog_2, IPPROTO_UDP)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to register (SQUARE_PROG, SQARE_VERS, udp).&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;transp = svctcp_create(RPC_ANYSOCK, 0, 0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (transp == NULL) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;cannot create tcp service.&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_register(transp, SQUARE_PROG, SQARE_VERS, square_prog_2, IPPROTO_TCP)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to register (SQUARE_PROG, SQARE_VERS, tcp).&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;svc_run ();<br/>&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;svc_run returned&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;exit (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;/* NOTREACHED */<br/>&#125;<br/> <br/><br/>蓝色部分是修改的地方，对比下面修改前的代码：<br/><br/>/* 修改前的文件<br/> * Please do not edit this file.<br/> * It was generated using rpcgen.<br/> */<br/><br/>#include &quot;square.h&quot;<br/>#include &lt;stdio.h&gt;<br/>#include &lt;stdlib.h&gt;<br/>#include &lt;rpc/pmap_clnt.h&gt;<br/>#include &lt;string.h&gt;<br/>#include &lt;memory.h&gt;<br/>#include &lt;sys/socket.h&gt;<br/>#include &lt;netinet/in.h&gt;<br/><br/>#ifndef SIG_PF<br/>#define SIG_PF void(*)(int)<br/>#endif<br/><br/>static void<br/>square_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;union &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;square_in squareproc_2_arg;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; argument;<br/>&nbsp;&nbsp;&nbsp;&nbsp;union &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;square_out squareproc_2_res;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125; result;<br/>&nbsp;&nbsp;&nbsp;&nbsp;bool_t retval;<br/>&nbsp;&nbsp;&nbsp;&nbsp;xdrproc_t _xdr_argument, _xdr_result;<br/>&nbsp;&nbsp;&nbsp;&nbsp;bool_t (*local)(char *, void *, struct svc_req *);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;switch (rqstp-&gt;rq_proc) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;case NULLPROC:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;case SQUAREPROC:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_xdr_argument = (xdrproc_t) xdr_square_in;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_xdr_result = (xdrproc_t) xdr_square_out;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local = (bool_t (*) (char *, void *, struct svc_req *))squareproc_2_svc;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;default:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svcerr_noproc (transp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;memset ((char *)&amp;argument, 0, sizeof (argument));<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &amp;argument)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svcerr_decode (transp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;retval = (bool_t) (*local)((char *)&amp;argument, (void *)&amp;result, rqstp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (retval &gt; 0 &amp;&amp; !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&amp;result)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svcerr_systemerr (transp);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &amp;argument)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to free arguments&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!square_prog_2_freeresult (transp, _xdr_result, (caddr_t) &amp;result))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to free results&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return;<br/>&#125;<br/><br/>int<br/>main (int argc, char **argv)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;register SVCXPRT *transp;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;pmap_unset (SQUARE_PROG, SQARE_VERS);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;transp = svcudp_create(RPC_ANYSOCK);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (transp == NULL) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;cannot create udp service.&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_register(transp, SQUARE_PROG, SQARE_VERS, square_prog_2, IPPROTO_UDP)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to register (SQUARE_PROG, SQARE_VERS, udp).&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;transp = svctcp_create(RPC_ANYSOCK, 0, 0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (transp == NULL) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;cannot create tcp service.&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (!svc_register(transp, SQUARE_PROG, SQARE_VERS, square_prog_2, IPPROTO_TCP)) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;unable to register (SQUARE_PROG, SQARE_VERS, tcp).&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;svc_run ();<br/>&nbsp;&nbsp;&nbsp;&nbsp;fprintf (stderr, &quot;%s&quot;, &quot;svc_run returned&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;exit (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;/* NOTREACHED */<br/>&#125;<br/><br/> <br/>可以看出，修改的思路就是把原square_prog_2函数功能改由serv_request来实现，让新的square_prog_2通过创建新线程来调用serv_request，serv_request则判断并调用相应的函数（在这个例子中只有SQUAREPROC一个函数）。实现的关键是要把struct svc_req *rqstp和 register SVCXPRT *transp这两个参数交给新线程函数serv_request处理，这样当serv_request返回时，便等价于原来的square_prog_2函数返回。<br/><br/>其它文件跟unp2e2上的例子一样<br/>/* 文件square_server.c<br/> * This is sample code generated by rpcgen.<br/> * These are only templates and you can use them<br/> * as a guideline for developing your own functions.<br/> */<br/><br/>#include &quot;square.h&quot;<br/><br/>bool_t<br/>squareproc_2_svc(square_in *inp, square_out *outp, struct svc_req *rqstp)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;bool_t retval;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Thread id = &#039;%ld&#039; started, arg = %d&#92;n&quot;,pthread_self(),inp-&gt;arg1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;sleep(5);<br/>&nbsp;&nbsp;&nbsp;&nbsp;outp-&gt;res1 = inp-&gt;arg1 * inp-&gt;arg1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Thread id = &#039;%ld&#039; is done %d &#92;n&quot;,pthread_self(),outp-&gt;res1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;retval = TRUE;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return retval;<br/>&#125;<br/><br/>int<br/>square_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;xdr_free (xdr_result, result);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/*<br/>&nbsp;&nbsp;&nbsp;&nbsp; * Insert additional freeing code here, if needed<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br/>&#125;<br/><br/> <br/><br/><br/>/*<br/><br/> *&nbsp;&nbsp; 该文件重写由rpcgen产生的原文件<br/><br/> *&nbsp;&nbsp; square_client.c<br/><br/><br/> */<br/><br/><br/>#include &quot;square.h&quot;<br/><br/>int <br/>main (int argc,char **argv)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;CLIENT *cl;<br/>&nbsp;&nbsp;&nbsp;&nbsp;square_in in;<br/>&nbsp;&nbsp;&nbsp;&nbsp;square_out out;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (argc != 3 ) &#123; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf (&quot;Usage : client &lt;hostname&gt; &lt;integer_valus&gt;&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;cl = clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, &quot;tcp&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp; if (cl == NULL) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clnt_sperror(cl, &quot;call failed&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit (1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;in.arg1 = atol(argv[2]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (squareproc_2(&amp;in, &amp;out, cl) != RPC_SUCCESS)&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s&#92;n&quot;, clnt_sperror(cl, argv[1]));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;result: %ld&#92;n&quot;,out.res1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;exit(0);<br/>&#125;<br/><br/> <br/><br/>接着编译链接server端和client端程序<br/><br/>$ gcc -o client square_clnt.c square_xdr.c square_client.c<br/>$ gcc -o server square_svc.c square_xdr.c square_server.c -lpthread<br/><br/> <br/><br/>在一个终端下运行./server记得打开portmap<br/>另一个终端下运行：<br/>$ ./client localhost 1 &amp; ./client localhost 2 &amp; ./client localhost 3<br/><br/>便能在server端看到：<br/>Thread id = &#039;1082132816&#039; started, arg = 3<br/>Thread id = &#039;1090525520&#039; started, arg = 2<br/>Thread id = &#039;1098918224&#039; started, arg = 1<br/>Thread id = &#039;1082132816&#039; is done 9 <br/>Thread id = &#039;1090525520&#039; is done 4 <br/>Thread id = &#039;1098918224&#039; is done 1 <br/> <br/> <br/> <br/>Hadoop里的RPC机制过程<br/>已经有文章描述RPC的具体结构，http://caibinbupt.javaeye.com/blog/280790，这篇文章很清晰的描述了Client和Server的结构，但是较为高屋建瓴，我在看的时候依然觉得无法清晰理解其调用过程，所以将过程整理出来，知道how，才容易理解why，即知道是怎么干的，才容易理解为什么会那么去设计。<br/><br/>客户端C要发起向服务端S的关于方法M调用<br/>1. C首先创建一个通向S的连接getConnection，然后将此次调用放入CallList里，这样客户端就可以同时发生很多调用，每个调用用ID来识别。<br/>2. 发送调用参数。调用参数是Client的调用方（比如NameNode，DataNode等）指定的，一般就是一个Invocation对象，里面包含要调用的方法和参数。了解JAVA动态代理类java.lang.reflect.Proxy会对这里的理解有很大帮助。<br/>3. 等待调用结果.Client.Connection是个线程类，启动了之后唯一做的时候就是等待调用结果<br/><br/>对于服务器端，其有一个方法start指定了启动服务器开始监听，这个start被四个类调用，分别是<br/>TaskTracker.initialize，Namenode.initialize,Jobtracker.offerService,<br/>Datanode.startDatanode<br/>显然，任何两者之间的通信都是考这个client-server模型实现的。<br/>server start后，干了三件事<br/>1. 启动listen，监听客户端Call<br/>2. 启动response，随时准备将处理结果发回client<br/>3. 启动10个handler，处理具体的请求。<br/><br/>这里必须对java NIO机制了解，才能看的明白。<br/><br/>当客户端调用来到的时候<br/>1. listen首先将调用doaccept将Connection附加给selectionkey，然后调用doread添加，doread会调用Connecton的方法将调用添加到调用列表，该列表是BlockingQueue，其保持列表先进先出的特性而且支持同步<br/>2. listen将call添加到calllist后，handler因为一直在检测calllist，于是其立刻开始处理，处理完毕后，其将结果保存在call对象中，然后调用response开始向客户端写。这里hadler调用的call只是一个未实现的方法，具体实现在RPC.Server中，这点需要注意。<br/>3. Response也监视responselist，如果responselist中某个call需要将结果写入客户端，就写出，当某个call的结果被发送完毕，从responselist中删除该call对象。<br/><br/>这里有个细节：handler完成call之后就开始向客户端写call结果，但是结果可能太多，无法通过一次性发送完毕，而发送之后还要等待client接受完毕才能再发，如果现在handler在那里等待客户端接受完毕，然后再发，效率不高。解决办法是handler处理完毕之后，只向client发送一次处理结果。如果这一次将处理结果发送完毕，接下来就没有response的事情了，如果没有发送完毕，接下来response负责将剩下的处理结果发送给客户端。这样handler的并发量会大一些。<br/><br/>服务器实现中大量利用监视队列，比如handler就直观坚持calllist，一旦发现数据就开始处理，而response就监视responselist，发现数据需要发送就开始发送。<br/><br/>写完了之后，觉得写的也不清楚，可能要清晰明白只能自己看代码吧。<br/>还发现在没用过java的情况下看hadoop可以更快的学习java<br/><br/><br/><br/>
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 什么是 RPC 及其Rpc编写的学习URL地址]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>