fms在centos linux 4.x上可以正常安装,装完了就可以自已自动启来了。但是在centos linux 5.x上,装完后启动不了。日志内也没有任何错误信息。
安装:
./installFMS -platformWarnOnly
安装完成后FMS服务没有自动启来,日志内也没有任何错误信息。
我们通过看/etc/init.d/fms这个启动脚本,发现FMS启动主要是用到了fmsmaster start。手动跑fmsmaster start发现出错。
[root@fms1 fms]# ./fmsmaster start
./fmsmaster: error while loading shared libraries: libssl.so.4: cannot open shared object file: No such file or directory
libssl.so.4是这个链接,在5.x上版本上没有建,手动建立:
[root@fms1 fms]# ln -s /usr/lib/libssl.so /usr/lib/libssl.so.4
再启动:
[root@fms1 fms]# ./fmsmaster start
./fmsmaster: error while loading shared libraries: libcrypto.so.4: cannot open shared object file: No such file or directory
再建链接:
[root@fms1 fms]# ln -s /usr/lib/libcrypto.so /usr/lib/libcrypto.so.4
OK,FMS可以正常启动了。
来源:http://hi.baidu.com/farmerluo/blog/item/32bfd42a7790d398023bf65e.html
参考:http://mimieye.iteye.com/blog/103755
http://blog.bj50.net/black/?p=184
下载:http://blog.csdn.net/xiang08/article/details/4136670
https://www.adobe.com/cfusion/tdrc/index.cfm?loc=zh_cn&product=flashmediaserver
安装:
./installFMS -platformWarnOnly
安装完成后FMS服务没有自动启来,日志内也没有任何错误信息。
我们通过看/etc/init.d/fms这个启动脚本,发现FMS启动主要是用到了fmsmaster start。手动跑fmsmaster start发现出错。
[root@fms1 fms]# ./fmsmaster start
./fmsmaster: error while loading shared libraries: libssl.so.4: cannot open shared object file: No such file or directory
libssl.so.4是这个链接,在5.x上版本上没有建,手动建立:
[root@fms1 fms]# ln -s /usr/lib/libssl.so /usr/lib/libssl.so.4
再启动:
[root@fms1 fms]# ./fmsmaster start
./fmsmaster: error while loading shared libraries: libcrypto.so.4: cannot open shared object file: No such file or directory
再建链接:
[root@fms1 fms]# ln -s /usr/lib/libcrypto.so /usr/lib/libcrypto.so.4
OK,FMS可以正常启动了。
来源:http://hi.baidu.com/farmerluo/blog/item/32bfd42a7790d398023bf65e.html
参考:http://mimieye.iteye.com/blog/103755
http://blog.bj50.net/black/?p=184
下载:http://blog.csdn.net/xiang08/article/details/4136670
https://www.adobe.com/cfusion/tdrc/index.cfm?loc=zh_cn&product=flashmediaserver
最近发现一个问题:
window.location.href在IE6下面竟然不跳转,这是为什么呢?
这个是我写的语句:
<a href="javascript:void(0);" ;onclick="javascript:window.location.href='http://www.sina.com';">转到新浪</a>
后面是网上找到了解决方案(URL:http://www.cnblogs.com/kaima/archive/2008/08/22/1273808.html):
<script type="text/javascript">
function goUrl(x)
{
window.location.href=x;
}
</script>
<a href="javascript:;" onclick="javascript:goUrl('http://www.sina.com');">跳转1</a>
<a href="javascript:void(0);" onclick="javascript:goUrl('http://www.sina.com');">跳转2</a>
<a href="javascript:void(0);" onclick="javascript:goUrl('http://www.sina.com');return false;">跳转3</a>
<a href="#" onclick="javascript:goUrl('http://www.sina.com');">跳转4</a>
<a href="###" onclick="javascript:goUrl('http://www.sina.com');">跳转5</a>
测试环境IE6,IE7,Firefox 3。
跳转1和2在IE6环境下无效,3、4、5在IE6,IE7,Firefox3.01下测试均能 通过,。
跳转4和5最简洁。
关键在于<a>的href属性,空链接用"#","###"。
为了不返回网页顶端。
空链接推荐用"###"。
我采用了第三种方法,在后面加了return false;这样,IE6、IE7、FF3下面全部通过。
如果这样:
注:"this.blur()"来消除链接后的焦点虚线框
来源:http://blog.163.com/leaf-shi/blog/static/12749133020098109215329/
window.location.href在IE6下面竟然不跳转,这是为什么呢?
这个是我写的语句:
<a href="javascript:void(0);" ;onclick="javascript:window.location.href='http://www.sina.com';">转到新浪</a>
后面是网上找到了解决方案(URL:http://www.cnblogs.com/kaima/archive/2008/08/22/1273808.html):
<script type="text/javascript">
function goUrl(x)
{
window.location.href=x;
}
</script>
<a href="javascript:;" onclick="javascript:goUrl('http://www.sina.com');">跳转1</a>
<a href="javascript:void(0);" onclick="javascript:goUrl('http://www.sina.com');">跳转2</a>
<a href="javascript:void(0);" onclick="javascript:goUrl('http://www.sina.com');return false;">跳转3</a>
<a href="#" onclick="javascript:goUrl('http://www.sina.com');">跳转4</a>
<a href="###" onclick="javascript:goUrl('http://www.sina.com');">跳转5</a>
测试环境IE6,IE7,Firefox 3。
跳转1和2在IE6环境下无效,3、4、5在IE6,IE7,Firefox3.01下测试均能 通过,。
跳转4和5最简洁。
关键在于<a>的href属性,空链接用"#","###"。
为了不返回网页顶端。
空链接推荐用"###"。
我采用了第三种方法,在后面加了return false;这样,IE6、IE7、FF3下面全部通过。
如果这样:
注:"this.blur()"来消除链接后的焦点虚线框
来源:http://blog.163.com/leaf-shi/blog/static/12749133020098109215329/
Smarty最大的功能是做模版的页面缓存。也就是通过Smarty可以完成两个步骤:编译+解析
第一步:编译。是指把模版文件的标签替换为纯php,再保存在缓存位置,保存的文件扩展名是PHP,我把这个步骤叫做编译(这是我自己的叫法,不是官方的)
第二步:解析。也就是把刚才编译的PHP文件解析执行而已~~这个就不用多做解释了
切入正题,在Smarty.class.php文件中加入如下代码
这个函数的作用就是保存文件~~
调用方法如下
来源:http://blog.163.com/junsheng_zheng/blog/static/110710882200911211162510/
第一步:编译。是指把模版文件的标签替换为纯php,再保存在缓存位置,保存的文件扩展名是PHP,我把这个步骤叫做编译(这是我自己的叫法,不是官方的)
第二步:解析。也就是把刚才编译的PHP文件解析执行而已~~这个就不用多做解释了
切入正题,在Smarty.class.php文件中加入如下代码
function MakeHtmlFile($file_name, $content)
{ //目录不存在就创建
if (!file_exists (dirname($file_name))) {
if (!@mkdir (dirname($file_name), 0777)) {
die($file_name."目录创建失败!");
}
}
if(!$fp = fopen($file_name, "w")){
echo "文件打开失败!";
return false;
}
if(!fwrite($fp, $content)){
echo "文件写入失败!";
fclose($fp);
return false;
}
fclose($fp);
chmod($file_name,0666);
}
{ //目录不存在就创建
if (!file_exists (dirname($file_name))) {
if (!@mkdir (dirname($file_name), 0777)) {
die($file_name."目录创建失败!");
}
}
if(!$fp = fopen($file_name, "w")){
echo "文件打开失败!";
return false;
}
if(!fwrite($fp, $content)){
echo "文件写入失败!";
fclose($fp);
return false;
}
fclose($fp);
chmod($file_name,0666);
}
这个函数的作用就是保存文件~~
调用方法如下
require '../libs/Smarty.class.php';
$smarty = new Smarty;
//…………省略变量定义和赋值
//$smarty->display('index.tpl');
$content=$smarty->fetch("index.tpl");
$smarty->MakeHtmlFile('./index.html',$content);//生成
$smarty = new Smarty;
//…………省略变量定义和赋值
//$smarty->display('index.tpl');
$content=$smarty->fetch("index.tpl");
$smarty->MakeHtmlFile('./index.html',$content);//生成
来源:http://blog.163.com/junsheng_zheng/blog/static/110710882200911211162510/
一:man 1,2,3,4,5,6
区段1:用户指令
区段2:系统调用
区段3:程序库调用
区段4:设备
区段5:文件格式
区段6:游戏
三:info 命令,网页形式,更详细。
二:/usr/share/doc
三:google,别百度。
阅读全文
区段1:用户指令
区段2:系统调用
区段3:程序库调用
区段4:设备
区段5:文件格式
区段6:游戏
三:info 命令,网页形式,更详细。
二:/usr/share/doc
三:google,别百度。

关于“RPC语言”
RPC语言也是一种专门的编程语言,当然这里我们不需要知道太多,只需要能看懂下面这种基本结构就行了:
program TESTPROG {
version VERSION {
string TEST(string) = 1;
} = 1;
} = 87654321;
这里TESTPROG和VERSION是两个变量,用于标识一个单独的RPC接口。这被RPC服务程序,比如portmap用到,我们可以不用关心,变量名字也是随便取的。但取值要在你的系统中是唯一的。
“string TEST(string) = 1;”这一行说明有两个函数test_VERSION和test_VERSION_svc,这里由于VERSION变量为1,所以函数名为test_1和 test_1_svc,这两个函数用于在服务器端和客户端实现调用,即:
在客户端调用test_1函数,服务器端调用test_1_svc函数处理并返回。
函数的类型是string,RPC语言中string即C里面的一个字符串。所以上述函数有一个字符串作为参数传递,同时要返回字符串。即:
char ** test_1(char **argp, CLIENT *clnt) 和 char **test_1_svc(char **argp, struct svc_req *rqstp)
同理,如果声明是这样的:
program RDICTPROG /* name of remote program ( not used ) */
{
version RDICTVERS /* declaration of version ( see below ) */
{
int INITW ( void ) = 1; /* first procedure in this program */
int INSERTW ( string ) = 2; /* second procedure in this program */
int DELETEW ( string ) = 3; /* third procedure in this program */
int LOOKUPW ( string ) = 4; /* fourth procedure in this program */
} = 1; /* definition of the program version */
} = 0x30090949; /* remote program number ( must be unique ) */
则说明这个RPC中有四个函数可用,即客户端可以调用initw_1、insertw_1、deletew_1、lookupw_1四个函数来向服务端发送消息,服务端可以用initw_1_svc、insertw_1_svc、deletew_1_svc、lookupw_1_svc四个函数来处理请求并返回结果。
原任务
假设现在有这样一个程序,源代码如下:
/* dict.c -- main, initw, nextin, insertw, deletew, lookupw */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXWORD 50 /* maximum length of a command or word */
#define DICTSIZ 100 /* maximum number of entries in dictionary. */
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
/* 函数原型 */
int nextin(char *cmd, char *word);
int initw(void);
int insertw(const char *word);
int deletew(const char *word);
int lookupw(const char *word);
/* ------------------------------------------------------------------
* main -- insert, delete, or lookup words in a dictionary as specified
* ------------------------------------------------------------------ */
int main(int argc, char *argv[])
{
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
printf("Please input:\n");
while (1) {
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
switch (cmd) {
case 'I': /* 初始化 */
initw();
printf("Dictionary initialized to empty.\n");
break;
case 'i': /* 插入 */
insertw(word);
printf("%s inserted.\n", word);
break;
case 'd': /* 删除 */
if (deletew(word)) {
printf("%s deleted.\n", word);
} else {
printf("%s not found.\n", word);
}
break;
case 'l': /* 查询 */
if (lookupw(word)) {
printf("%s was found.\n", word);
} else {
printf("%s was not found.\n", word);
}
break;
case 'q': /* 退出 */
printf("Program quits.\n");
exit(0);
break;
default: /* 非法输入 */
printf("command %c invalid.\n", cmd);
break;
} /* end of switch */
} /* end of while */
return 0;
} /* end of main */
/* ------------------------------------------------------------------
* nextin -- read a command and(possibly) a word from the next input line
* ------------------------------------------------------------------ */
int nextin(char *cmd, char *word)
{
int i, ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
*cmd = (char) ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
if (ch == '\n') {
return (0);
}
i = 0;
while (!isspace(ch)) {
if (++i > MAXWORD) {
printf("error: word too long.\n");
exit(1);
}
*word++ = ch;
ch = getc(stdin);
} /* end of while */
*word = '\0'; /* 原来的代码这里有问题 */
return i;
} /* end of nextin */
/* ------------------------------------------------------------------
* initw -- initialize the dictionary to contain no words at all
* ------------------------------------------------------------------ */
int initw(void)
{
nwords = 0;
return 1;
} /* end of initw */
/* ------------------------------------------------------------------
* insertw -- insert a word in the dictionary
* ------------------------------------------------------------------ */
int insertw(const char *word)
{
strcpy(dict[nwords], word);
nwords++;
return (nwords);
} /* end of insertw */
/* ------------------------------------------------------------------
* deletew -- delete a word from the dictionary
* ------------------------------------------------------------------ */
int deletew(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
nwords--;
strcpy(dict[i], dict[nwords]);
return (1);
}
} /* end of for */
return (0);
} /* end of deletew */
/* ------------------------------------------------------------------
* lookupw -- look up a word in the dictionary
* ------------------------------------------------------------------ */
int lookupw(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
return (1);
}
} /* end of for */
return (0);
} /* end of lookupw */
这是一个简单的字典程序,即程序运行起来以后维护着一个字典库,用户可以向里面添加词语,也可以查询或删除词语。
当然,这个程序只能在同一台主机上运行。程序整个运行过程中,只需要完成如下几个步骤:
A、接受用户输入;
B、分析用户输入决定是否进行下面的步骤:
1、初始化数据库;
2、向数据库添加词语;
3、查询或删除词语
任务分解
大家可以想到,对于一个大型系统,比如需要有很多人维护这个系统的数据。象上面这样独立的程序就不适用了,需要做成分布式系统:
即一个服务器维护着数据库,任何客户端都可以接受用户请求,客户端分析用户命令后提交给服务器去处理。
所以我们可能会把程序分成两部分:
客户端:接受用户输入,并判断用户输入内容的正确性,向服务器提交数据,等服务器返回消息
服务器端:维护数据,接受客户端命令并执行后返回结果。
所以我们把上面这个程序分解成下面两部分:
/* dict1.c -- main, nextin */
#include <stdio.h>
#include <stdlib.h>
#define MAXWORD 50 /* maximum length of a command or word */
/* ------------------------------------------------------------------
* main -- insert, delete, or lookup words in a dictionary as specified
* ------------------------------------------------------------------ */
int main(int argc, char *argv[])
{
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
printf("Please input:\n");
while (1) {
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
switch (cmd) {
case 'I': /* 初始化 */
initw();
printf("Dictionary initialized to empty.\n");
break;
case 'i': /* 插入 */
insertw(word);
printf("%s inserted.\n", word);
break;
case 'd': /* 删除 */
if (deletew(word)) {
printf("%s deleted.\n", word);
} else {
printf("%s not found.\n", word);
}
break;
case 'l': /* 查询 */
if (lookupw(word)) {
printf("%s was found.\n", word);
} else {
printf("%s was not found.\n", word);
}
break;
case 'q': /* 退出 */
printf("Program quits.\n");
exit(0);
break;
default: /* 非法输入 */
printf("command %c invalid.\n", cmd);
break;
} /* end of switch */
} /* end of while */
return 0;
} /* end of main */
/* ------------------------------------------------------------------
* nextin -- read a command and(possibly) a word from the next input line
* ------------------------------------------------------------------ */
int nextin(char *cmd, char *word)
{
int i, ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
*cmd = (char) ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
if (ch == '\n') {
return (0);
}
i = 0;
while (!isspace(ch)) {
if (++i > MAXWORD) {
printf("error: word too long.\n");
exit(1);
}
*word++ = ch;
ch = getc(stdin);
} /* end of while */
*word = '\0';
return i;
} /* end of nextin */
和
/* dict2.c -- initw, insertw, deletew, lookupw */
#include <string.h>
#define MAXWORD 50 /* maximum length of a command or word */
#define DICTSIZ 100 /* maximum number of entries in dictionary. */
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
/* ------------------------------------------------------------------
* initw -- initialize the dictionary to contain no words at all
* ------------------------------------------------------------------ */
int initw(void)
{
nwords = 0;
return 1;
} /* end of initw */
/* ------------------------------------------------------------------
* insertw -- insert a word in the dictionary
* ------------------------------------------------------------------ */
int insertw(const char *word)
{
strcpy(dict[nwords], word);
nwords++;
return (nwords);
} /* end of insertw */
/* ------------------------------------------------------------------
* deletew -- delete a word from the dictionary
* ------------------------------------------------------------------ */
int deletew(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
nwords--;
strcpy(dict[i], dict[nwords]);
return (1);
}
} /* end of for */
return (0);
} /* end of deletew */
/* ------------------------------------------------------------------
* lookupw -- look up a word in the dictionary
* ------------------------------------------------------------------ */
int lookupw(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
return (1);
}
} /* end of for */
return (0);
} /* end of lookupw */
这两部分代码只是在功能上实现了分离,显然实现通讯的部分还没有,下面我们利用RPC来快速实现通讯。
利用RPC实现分布式系统
首先,建立一个RPC源文件,源代码rdict.x如下:
/* rdict.x */
/* RPC declarations for dictionary program */
const MAXWORD = 10; /* maximum length of a command or word */
const DICTSIZ = 3; /* number of entries in dictionary */
struct example /* unused structure declared here to */
{
int exfield1; /* illustrate how rpcgen builds XDR */
char exfield2; /* routines to convert structures */
};
/* ------------------------------------------------------------------
* RDICTPROG -- remote program that provides insert, delete, and lookup
* ------------------------------------------------------------------ */
program RDICTPROG /* name of remote program ( not used ) */
{
version RDICTVERS /* declaration of version ( see below ) */
{
int INITW ( void ) = 1; /* first procedure in this program */
int INSERTW ( string ) = 2; /* second procedure in this program */
int DELETEW ( string ) = 3; /* third procedure in this program */
int LOOKUPW ( string ) = 4; /* fourth procedure in this program */
} = 1; /* definition of the program version */
} = 0x30090949; /* remote program number ( must be unique ) */
然后用下列命令产生服务器端函数rdict_srv_func.c:
rpcgen -Ss -o rdict_srv_func.c rdict.x
然后用下列命令产生客户端程序rdict_client.c:
rpcgen -Sc -o rdict_client.c rdict.x
/************关于本文档********************************************
*filename: 我是这样学习Linux下C语言编程的-利用RPC快速实现分布式系统
*purpose: 说明如何利用RPC快速进行客户端-服务器端C-S结构编程
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-02-27 19:20
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to:
* Ubuntu 本程序在Ubuntu 6.10系统上测试完全正常
* Google.com 我通过google搜索并参考了RPC编程相关的许多文章
* 网络安全焦点(www.xfocus.net) 我主要借鉴了此文 http://www.xfocus.net/articles/200009/10.html
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
然后用下列命令产生Makefile:
rpcgen -Sm rdict.x > Makefile
Makefile文件原内容如下:
# This is a template Makefile generated by rpcgen
# Parameters
CLIENT = rdict_client
SERVER = rdict_server
SOURCES_CLNT.c =
SOURCES_CLNT.h =
SOURCES_SVC.c =
SOURCES_SVC.h =
SOURCES.x = rdict.x
TARGETS_SVC.c = rdict_svc.c rdict_xdr.c
TARGETS_CLNT.c = rdict_clnt.c rdict_xdr.c
TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c
OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags
CFLAGS += -g
LDLIBS += -lnsl
RPCGENFLAGS =
# Targets
all : $(CLIENT) $(SERVER)
$(TARGETS) : $(SOURCES.x)
rpcgen $(RPCGENFLAGS) $(SOURCES.x)
$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)
$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)
$(CLIENT) : $(OBJECTS_CLNT)
$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)
$(SERVER) : $(OBJECTS_SVC)
$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)
clean:
$(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)
动手修改Makefile,修改后内容如下:
# This is a template Makefile generated by rpcgen
# Parameters
CLIENT = rdict_client
SERVER = rdict_server
SOURCES_CLNT.c =
SOURCES_CLNT.h =
SOURCES_SVC.c =
SOURCES_SVC.h =
SOURCES.x = rdict.x
TARGETS_SVC.c = rdict_svc.c rdict_xdr.c rdict_srv_func.c
TARGETS_CLNT.c = rdict_clnt.c rdict_xdr.c rdict_client.c
TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c
OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags
CFLAGS += -g
LDLIBS += -lnsl
RPCGENFLAGS =
# Targets
all : $(CLIENT) $(SERVER)
$(TARGETS) : $(SOURCES.x)
rpcgen $(RPCGENFLAGS) $(SOURCES.x)
$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)
$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)
$(CLIENT) : $(OBJECTS_CLNT)
$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)
$(SERVER) : $(OBJECTS_SVC)
$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)
clean:
$(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER) *~
修改客户端源代码rdict_client.c,把接受用户输入并分析用户输入内容的部分加到程序中来。修改后的代码为:
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/
#include "rdict.h"
/* ------------------------------------------------------------------
* nextin -- read a command and(possibly) a word from the next input line
* ------------------------------------------------------------------ */
int nextin(char *cmd, char *word)
{
int i, ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
*cmd = (char) ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
if (ch == '\n') {
return (0);
}
i = 0;
while (!isspace(ch)) {
if (++i > MAXWORD) {
printf("error: word too long.\n");
exit(1);
}
*word++ = ch;
ch = getc(stdin);
} /* end of while */
*word = '\0';
return i;
} /* end of nextin */
void rdictprog_1(char *host)
{
CLIENT *clnt;
int *result_1;
char *initw_1_arg;
int *result_2;
char *insertw_1_arg;
int *result_3;
char *deletew_1_arg;
int *result_4;
char *lookupw_1_arg;
#ifndef DEBUG
clnt = clnt_create(host, RDICTPROG, RDICTVERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror(host);
exit(1);
}
#endif /* DEBUG */
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
while (1) {
printf("\nPlease input:");
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
/* printf("\nYour cmd is:%c, your word is:%s\n", cmd, word); */
switch (cmd) {
case 'I': /* 初始化 */
result_1 = initw_1((void *) &initw_1_arg, clnt);
/* printf("\nYour result is:%d\n", *result_1); */
if (result_1 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
if(*result_1 ==0) printf("Dictionary initialized to empty.\n");
else printf("Dictionary have already initialized.\n");
break;
case 'i': /* 插入 */
insertw_1_arg = word;
result_2 = insertw_1(&insertw_1_arg, clnt);
/* printf("\nYour result is:%d, your string is:%s(%d)\n", *result_2, insertw_1_arg, strlen(insertw_1_arg)); */
if (result_2 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
printf("%s inserted.\n", word);
break;
case 'd': /* 删除 */
deletew_1_arg = word;
result_3 = deletew_1(&deletew_1_arg, clnt);
/* printf("\nYour result is:%d, your string is:%s(%d)\n", *result_3, deletew_1_arg, strlen(deletew_1_arg)); */
if (result_3 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
printf("%s deleted.\n", word);
break;
case 'l': /* 查询 */
lookupw_1_arg = word;
result_4 = lookupw_1(&lookupw_1_arg, clnt);
/* printf("\nYour result is:%d, your string is:%s(%d)\n", *result_4, lookupw_1_arg, strlen(lookupw_1_arg)); */
if (result_4 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
if(*result_4 ==0) printf("%s found.\n", word);
else printf("%s not found.\n", word);
break;
case 'q': /* 退出 */
printf("Program quits.\n");
exit(0);
break;
default: /* 非法输入 */
printf("Command %c(%s) invalid.\n", cmd, word);
break;
} /* end of switch */
} /* end of while */
#ifndef DEBUG
clnt_destroy(clnt);
#endif /* DEBUG */
}
int main(int argc, char *argv[])
{
char *host;
if (argc < 2) {
printf("usage: %s server_host\n", argv[0]);
exit(1);
}
host = argv[1];
rdictprog_1(host);
exit(0);
}
同时修改服务器端代码rdict_srv_func.c,修改后内容为:
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/
#include "rdict.h"
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
char init_bool = 0;
int initw(void)
{
if(init_bool) return 1;
nwords = 0;
init_bool = 1;
return 0;
} /* end of initw */
/* ------------------------------------------------------------------
* insertw -- insert a word in the dictionary
* ------------------------------------------------------------------ */
int insertw(const char *word)
{
strcpy(dict[nwords%DICTSIZ], word);
nwords++;
return (nwords);
} /* end of insertw */
/* ------------------------------------------------------------------
* deletew -- delete a word from the dictionary
* ------------------------------------------------------------------ */
int deletew(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
nwords--;
strcpy(dict[i], dict[nwords]);
return (1);
}
} /* end of for */
return (0);
} /* end of deletew */
/* ------------------------------------------------------------------
* lookupw -- look up a word in the dictionary
* ------------------------------------------------------------------ */
int lookupw(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
return 0;
}
} /* end of for */
return 1;
} /* end of lookupw */
int *initw_1_svc(void *argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = initw();
return &result;
}
int *insertw_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = insertw(*argp);
return &result;
}
int *deletew_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = deletew(*argp);
return &result;
}
int *lookupw_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = lookupw(*argp);
return &result;
}
至此,程序做好了。输入一个make命令就可以生成test_server和test_client这两个可执行程序了。
在一台机器上运行./test_server程序,在另外的客户机上运行./test_client server_ip就可以了。这里server_ip是运行着test_server程序的主机的IP地址。
阅读全文
RPC语言也是一种专门的编程语言,当然这里我们不需要知道太多,只需要能看懂下面这种基本结构就行了:
program TESTPROG {
version VERSION {
string TEST(string) = 1;
} = 1;
} = 87654321;
这里TESTPROG和VERSION是两个变量,用于标识一个单独的RPC接口。这被RPC服务程序,比如portmap用到,我们可以不用关心,变量名字也是随便取的。但取值要在你的系统中是唯一的。
“string TEST(string) = 1;”这一行说明有两个函数test_VERSION和test_VERSION_svc,这里由于VERSION变量为1,所以函数名为test_1和 test_1_svc,这两个函数用于在服务器端和客户端实现调用,即:
在客户端调用test_1函数,服务器端调用test_1_svc函数处理并返回。
函数的类型是string,RPC语言中string即C里面的一个字符串。所以上述函数有一个字符串作为参数传递,同时要返回字符串。即:
char ** test_1(char **argp, CLIENT *clnt) 和 char **test_1_svc(char **argp, struct svc_req *rqstp)
同理,如果声明是这样的:
program RDICTPROG /* name of remote program ( not used ) */
{
version RDICTVERS /* declaration of version ( see below ) */
{
int INITW ( void ) = 1; /* first procedure in this program */
int INSERTW ( string ) = 2; /* second procedure in this program */
int DELETEW ( string ) = 3; /* third procedure in this program */
int LOOKUPW ( string ) = 4; /* fourth procedure in this program */
} = 1; /* definition of the program version */
} = 0x30090949; /* remote program number ( must be unique ) */
则说明这个RPC中有四个函数可用,即客户端可以调用initw_1、insertw_1、deletew_1、lookupw_1四个函数来向服务端发送消息,服务端可以用initw_1_svc、insertw_1_svc、deletew_1_svc、lookupw_1_svc四个函数来处理请求并返回结果。
原任务
假设现在有这样一个程序,源代码如下:
/* dict.c -- main, initw, nextin, insertw, deletew, lookupw */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXWORD 50 /* maximum length of a command or word */
#define DICTSIZ 100 /* maximum number of entries in dictionary. */
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
/* 函数原型 */
int nextin(char *cmd, char *word);
int initw(void);
int insertw(const char *word);
int deletew(const char *word);
int lookupw(const char *word);
/* ------------------------------------------------------------------
* main -- insert, delete, or lookup words in a dictionary as specified
* ------------------------------------------------------------------ */
int main(int argc, char *argv[])
{
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
printf("Please input:\n");
while (1) {
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
switch (cmd) {
case 'I': /* 初始化 */
initw();
printf("Dictionary initialized to empty.\n");
break;
case 'i': /* 插入 */
insertw(word);
printf("%s inserted.\n", word);
break;
case 'd': /* 删除 */
if (deletew(word)) {
printf("%s deleted.\n", word);
} else {
printf("%s not found.\n", word);
}
break;
case 'l': /* 查询 */
if (lookupw(word)) {
printf("%s was found.\n", word);
} else {
printf("%s was not found.\n", word);
}
break;
case 'q': /* 退出 */
printf("Program quits.\n");
exit(0);
break;
default: /* 非法输入 */
printf("command %c invalid.\n", cmd);
break;
} /* end of switch */
} /* end of while */
return 0;
} /* end of main */
/* ------------------------------------------------------------------
* nextin -- read a command and(possibly) a word from the next input line
* ------------------------------------------------------------------ */
int nextin(char *cmd, char *word)
{
int i, ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
*cmd = (char) ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
if (ch == '\n') {
return (0);
}
i = 0;
while (!isspace(ch)) {
if (++i > MAXWORD) {
printf("error: word too long.\n");
exit(1);
}
*word++ = ch;
ch = getc(stdin);
} /* end of while */
*word = '\0'; /* 原来的代码这里有问题 */
return i;
} /* end of nextin */
/* ------------------------------------------------------------------
* initw -- initialize the dictionary to contain no words at all
* ------------------------------------------------------------------ */
int initw(void)
{
nwords = 0;
return 1;
} /* end of initw */
/* ------------------------------------------------------------------
* insertw -- insert a word in the dictionary
* ------------------------------------------------------------------ */
int insertw(const char *word)
{
strcpy(dict[nwords], word);
nwords++;
return (nwords);
} /* end of insertw */
/* ------------------------------------------------------------------
* deletew -- delete a word from the dictionary
* ------------------------------------------------------------------ */
int deletew(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
nwords--;
strcpy(dict[i], dict[nwords]);
return (1);
}
} /* end of for */
return (0);
} /* end of deletew */
/* ------------------------------------------------------------------
* lookupw -- look up a word in the dictionary
* ------------------------------------------------------------------ */
int lookupw(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
return (1);
}
} /* end of for */
return (0);
} /* end of lookupw */
这是一个简单的字典程序,即程序运行起来以后维护着一个字典库,用户可以向里面添加词语,也可以查询或删除词语。
当然,这个程序只能在同一台主机上运行。程序整个运行过程中,只需要完成如下几个步骤:
A、接受用户输入;
B、分析用户输入决定是否进行下面的步骤:
1、初始化数据库;
2、向数据库添加词语;
3、查询或删除词语
任务分解
大家可以想到,对于一个大型系统,比如需要有很多人维护这个系统的数据。象上面这样独立的程序就不适用了,需要做成分布式系统:
即一个服务器维护着数据库,任何客户端都可以接受用户请求,客户端分析用户命令后提交给服务器去处理。
所以我们可能会把程序分成两部分:
客户端:接受用户输入,并判断用户输入内容的正确性,向服务器提交数据,等服务器返回消息
服务器端:维护数据,接受客户端命令并执行后返回结果。
所以我们把上面这个程序分解成下面两部分:
/* dict1.c -- main, nextin */
#include <stdio.h>
#include <stdlib.h>
#define MAXWORD 50 /* maximum length of a command or word */
/* ------------------------------------------------------------------
* main -- insert, delete, or lookup words in a dictionary as specified
* ------------------------------------------------------------------ */
int main(int argc, char *argv[])
{
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
printf("Please input:\n");
while (1) {
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
switch (cmd) {
case 'I': /* 初始化 */
initw();
printf("Dictionary initialized to empty.\n");
break;
case 'i': /* 插入 */
insertw(word);
printf("%s inserted.\n", word);
break;
case 'd': /* 删除 */
if (deletew(word)) {
printf("%s deleted.\n", word);
} else {
printf("%s not found.\n", word);
}
break;
case 'l': /* 查询 */
if (lookupw(word)) {
printf("%s was found.\n", word);
} else {
printf("%s was not found.\n", word);
}
break;
case 'q': /* 退出 */
printf("Program quits.\n");
exit(0);
break;
default: /* 非法输入 */
printf("command %c invalid.\n", cmd);
break;
} /* end of switch */
} /* end of while */
return 0;
} /* end of main */
/* ------------------------------------------------------------------
* nextin -- read a command and(possibly) a word from the next input line
* ------------------------------------------------------------------ */
int nextin(char *cmd, char *word)
{
int i, ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
*cmd = (char) ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
if (ch == '\n') {
return (0);
}
i = 0;
while (!isspace(ch)) {
if (++i > MAXWORD) {
printf("error: word too long.\n");
exit(1);
}
*word++ = ch;
ch = getc(stdin);
} /* end of while */
*word = '\0';
return i;
} /* end of nextin */
和
/* dict2.c -- initw, insertw, deletew, lookupw */
#include <string.h>
#define MAXWORD 50 /* maximum length of a command or word */
#define DICTSIZ 100 /* maximum number of entries in dictionary. */
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
/* ------------------------------------------------------------------
* initw -- initialize the dictionary to contain no words at all
* ------------------------------------------------------------------ */
int initw(void)
{
nwords = 0;
return 1;
} /* end of initw */
/* ------------------------------------------------------------------
* insertw -- insert a word in the dictionary
* ------------------------------------------------------------------ */
int insertw(const char *word)
{
strcpy(dict[nwords], word);
nwords++;
return (nwords);
} /* end of insertw */
/* ------------------------------------------------------------------
* deletew -- delete a word from the dictionary
* ------------------------------------------------------------------ */
int deletew(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
nwords--;
strcpy(dict[i], dict[nwords]);
return (1);
}
} /* end of for */
return (0);
} /* end of deletew */
/* ------------------------------------------------------------------
* lookupw -- look up a word in the dictionary
* ------------------------------------------------------------------ */
int lookupw(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
return (1);
}
} /* end of for */
return (0);
} /* end of lookupw */
这两部分代码只是在功能上实现了分离,显然实现通讯的部分还没有,下面我们利用RPC来快速实现通讯。
利用RPC实现分布式系统
首先,建立一个RPC源文件,源代码rdict.x如下:
/* rdict.x */
/* RPC declarations for dictionary program */
const MAXWORD = 10; /* maximum length of a command or word */
const DICTSIZ = 3; /* number of entries in dictionary */
struct example /* unused structure declared here to */
{
int exfield1; /* illustrate how rpcgen builds XDR */
char exfield2; /* routines to convert structures */
};
/* ------------------------------------------------------------------
* RDICTPROG -- remote program that provides insert, delete, and lookup
* ------------------------------------------------------------------ */
program RDICTPROG /* name of remote program ( not used ) */
{
version RDICTVERS /* declaration of version ( see below ) */
{
int INITW ( void ) = 1; /* first procedure in this program */
int INSERTW ( string ) = 2; /* second procedure in this program */
int DELETEW ( string ) = 3; /* third procedure in this program */
int LOOKUPW ( string ) = 4; /* fourth procedure in this program */
} = 1; /* definition of the program version */
} = 0x30090949; /* remote program number ( must be unique ) */
然后用下列命令产生服务器端函数rdict_srv_func.c:
rpcgen -Ss -o rdict_srv_func.c rdict.x
然后用下列命令产生客户端程序rdict_client.c:
rpcgen -Sc -o rdict_client.c rdict.x
/************关于本文档********************************************
*filename: 我是这样学习Linux下C语言编程的-利用RPC快速实现分布式系统
*purpose: 说明如何利用RPC快速进行客户端-服务器端C-S结构编程
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-02-27 19:20
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to:
* Ubuntu 本程序在Ubuntu 6.10系统上测试完全正常
* Google.com 我通过google搜索并参考了RPC编程相关的许多文章
* 网络安全焦点(www.xfocus.net) 我主要借鉴了此文 http://www.xfocus.net/articles/200009/10.html
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
然后用下列命令产生Makefile:
rpcgen -Sm rdict.x > Makefile
Makefile文件原内容如下:
# This is a template Makefile generated by rpcgen
# Parameters
CLIENT = rdict_client
SERVER = rdict_server
SOURCES_CLNT.c =
SOURCES_CLNT.h =
SOURCES_SVC.c =
SOURCES_SVC.h =
SOURCES.x = rdict.x
TARGETS_SVC.c = rdict_svc.c rdict_xdr.c
TARGETS_CLNT.c = rdict_clnt.c rdict_xdr.c
TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c
OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags
CFLAGS += -g
LDLIBS += -lnsl
RPCGENFLAGS =
# Targets
all : $(CLIENT) $(SERVER)
$(TARGETS) : $(SOURCES.x)
rpcgen $(RPCGENFLAGS) $(SOURCES.x)
$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)
$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)
$(CLIENT) : $(OBJECTS_CLNT)
$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)
$(SERVER) : $(OBJECTS_SVC)
$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)
clean:
$(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)
动手修改Makefile,修改后内容如下:
# This is a template Makefile generated by rpcgen
# Parameters
CLIENT = rdict_client
SERVER = rdict_server
SOURCES_CLNT.c =
SOURCES_CLNT.h =
SOURCES_SVC.c =
SOURCES_SVC.h =
SOURCES.x = rdict.x
TARGETS_SVC.c = rdict_svc.c rdict_xdr.c rdict_srv_func.c
TARGETS_CLNT.c = rdict_clnt.c rdict_xdr.c rdict_client.c
TARGETS = rdict.h rdict_xdr.c rdict_clnt.c rdict_svc.c
OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags
CFLAGS += -g
LDLIBS += -lnsl
RPCGENFLAGS =
# Targets
all : $(CLIENT) $(SERVER)
$(TARGETS) : $(SOURCES.x)
rpcgen $(RPCGENFLAGS) $(SOURCES.x)
$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)
$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)
$(CLIENT) : $(OBJECTS_CLNT)
$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)
$(SERVER) : $(OBJECTS_SVC)
$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)
clean:
$(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER) *~
修改客户端源代码rdict_client.c,把接受用户输入并分析用户输入内容的部分加到程序中来。修改后的代码为:
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/
#include "rdict.h"
/* ------------------------------------------------------------------
* nextin -- read a command and(possibly) a word from the next input line
* ------------------------------------------------------------------ */
int nextin(char *cmd, char *word)
{
int i, ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
*cmd = (char) ch;
ch = getc(stdin);
while (isspace(ch)) {
ch = getc(stdin);
} /* end of while */
if (ch == EOF) {
return (-1);
}
if (ch == '\n') {
return (0);
}
i = 0;
while (!isspace(ch)) {
if (++i > MAXWORD) {
printf("error: word too long.\n");
exit(1);
}
*word++ = ch;
ch = getc(stdin);
} /* end of while */
*word = '\0';
return i;
} /* end of nextin */
void rdictprog_1(char *host)
{
CLIENT *clnt;
int *result_1;
char *initw_1_arg;
int *result_2;
char *insertw_1_arg;
int *result_3;
char *deletew_1_arg;
int *result_4;
char *lookupw_1_arg;
#ifndef DEBUG
clnt = clnt_create(host, RDICTPROG, RDICTVERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror(host);
exit(1);
}
#endif /* DEBUG */
char word[MAXWORD + 1]; /* space to hold word from input line */
char cmd;
int wordlen; /* length of input word */
while (1) {
printf("\nPlease input:");
wordlen = nextin(&cmd, word);
if (wordlen < 0) {
exit(0);
}
/* printf("\nYour cmd is:%c, your word is:%s\n", cmd, word); */
switch (cmd) {
case 'I': /* 初始化 */
result_1 = initw_1((void *) &initw_1_arg, clnt);
/* printf("\nYour result is:%d\n", *result_1); */
if (result_1 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
if(*result_1 ==0) printf("Dictionary initialized to empty.\n");
else printf("Dictionary have already initialized.\n");
break;
case 'i': /* 插入 */
insertw_1_arg = word;
result_2 = insertw_1(&insertw_1_arg, clnt);
/* printf("\nYour result is:%d, your string is:%s(%d)\n", *result_2, insertw_1_arg, strlen(insertw_1_arg)); */
if (result_2 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
printf("%s inserted.\n", word);
break;
case 'd': /* 删除 */
deletew_1_arg = word;
result_3 = deletew_1(&deletew_1_arg, clnt);
/* printf("\nYour result is:%d, your string is:%s(%d)\n", *result_3, deletew_1_arg, strlen(deletew_1_arg)); */
if (result_3 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
printf("%s deleted.\n", word);
break;
case 'l': /* 查询 */
lookupw_1_arg = word;
result_4 = lookupw_1(&lookupw_1_arg, clnt);
/* printf("\nYour result is:%d, your string is:%s(%d)\n", *result_4, lookupw_1_arg, strlen(lookupw_1_arg)); */
if (result_4 == (int *) NULL)
clnt_perror(clnt, "call failed");
else
if(*result_4 ==0) printf("%s found.\n", word);
else printf("%s not found.\n", word);
break;
case 'q': /* 退出 */
printf("Program quits.\n");
exit(0);
break;
default: /* 非法输入 */
printf("Command %c(%s) invalid.\n", cmd, word);
break;
} /* end of switch */
} /* end of while */
#ifndef DEBUG
clnt_destroy(clnt);
#endif /* DEBUG */
}
int main(int argc, char *argv[])
{
char *host;
if (argc < 2) {
printf("usage: %s server_host\n", argv[0]);
exit(1);
}
host = argv[1];
rdictprog_1(host);
exit(0);
}
同时修改服务器端代码rdict_srv_func.c,修改后内容为:
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/
#include "rdict.h"
char dict[DICTSIZ][MAXWORD + 1]; /* storage for a dictionary of words */
int nwords = 0; /* number of words in the dictionary */
char init_bool = 0;
int initw(void)
{
if(init_bool) return 1;
nwords = 0;
init_bool = 1;
return 0;
} /* end of initw */
/* ------------------------------------------------------------------
* insertw -- insert a word in the dictionary
* ------------------------------------------------------------------ */
int insertw(const char *word)
{
strcpy(dict[nwords%DICTSIZ], word);
nwords++;
return (nwords);
} /* end of insertw */
/* ------------------------------------------------------------------
* deletew -- delete a word from the dictionary
* ------------------------------------------------------------------ */
int deletew(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
nwords--;
strcpy(dict[i], dict[nwords]);
return (1);
}
} /* end of for */
return (0);
} /* end of deletew */
/* ------------------------------------------------------------------
* lookupw -- look up a word in the dictionary
* ------------------------------------------------------------------ */
int lookupw(const char *word)
{
int i;
for (i = 0; i < nwords; i++) {
if (strcmp(word, dict[i]) == 0) {
return 0;
}
} /* end of for */
return 1;
} /* end of lookupw */
int *initw_1_svc(void *argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = initw();
return &result;
}
int *insertw_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = insertw(*argp);
return &result;
}
int *deletew_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = deletew(*argp);
return &result;
}
int *lookupw_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
/*
* insert server code here
*/
result = lookupw(*argp);
return &result;
}
至此,程序做好了。输入一个make命令就可以生成test_server和test_client这两个可执行程序了。
在一台机器上运行./test_server程序,在另外的客户机上运行./test_client server_ip就可以了。这里server_ip是运行着test_server程序的主机的IP地址。

nginx现在正在以光的速度蔓延开来,他以其稳定性和高性能等众多优点迅速扩大市场,大家都知道,nginx是以单线程为基础的,那么他怎么能在并发性上取得优势的呢?会不会因为网络阻塞而导致主线程阻塞呢?下面就相关问题作一些概念性的阐述。
这篇文章写得好还有代码从自己角度来说nginx的epoll架构,AddTime:2015-02-03
http://blog.csdn.net/zhaoxy_thu/article/details/24624729
阅读全文
这篇文章写得好还有代码从自己角度来说nginx的epoll架构,AddTime:2015-02-03
http://blog.csdn.net/zhaoxy_thu/article/details/24624729

程序员世界里有哪些名言警局呢?Jun Auza 列出了一些启迪人心的至理名言,它们大多来自产业界富于经验的人们。
下文列出前10个供读者欣赏。
10. "People think that computer science is the art of geniuses but the actual reality is the opposite, just many people doing things that build on each other, like a wall of mini stones."- Donald Knuth
10. “人们认为计算机科学是天才的艺术,但事实完全相反:只是很多人在共同建立起来的事物之上工作,就像一条由小石头铺成的小径。”—— Donald Knuth
9. “First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack.”- George Carrette
9. “首先学会计算机科学和所有的理论。然后发展出一个编程风格。之后便要忘掉所有这些,以自由的方式探索。”—— George Carrette
8. “Most of you are familiar with the virtues of a programmer. There are three, of course: laziness, impatience, and hubris.”- Larry Wall
8. “大多数的你们都熟悉程序员的美德。它们有三点:懒,不耐烦,以及狂妄自大。”—— Larry Wall
7. “Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other,with no structural integrity, but just done by brute force and thousands of slaves.”- Alan Kay
7. “今日的大多数软件很像埃及金字塔,由千百万砖头堆砌起来,层层相切,没有着整体的结构,是由畜力和成千上万奴隶的力量建立起来的。”—— Alan Kay
6. “The trouble with programmers is that you can never tell what a programmer is doing until it’s too late.”- Seymour Cray
6. “程序员的问题是,不到太晚,你永远无法知道一个他在做着些什么。”—— Seymour Cray
5. “To iterate is human, to recurse divine.”- L. Peter Deutsch
5. “人理解迭代,神理解递归。”—— Peter Deutsch
4. "On two occasions I have been asked [by members of Parliament]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."- Charles Babbage
4. “有两次我被(国会议员)问道:‘ Mr. Babbage,如果你输入计算机错误的数据,正确的答案会出来吗?’我完全无法理解能产生此种问题的大脑的混乱。”
3. "Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program."- Linus Torvalds
3. “大部分好的程序员编程并不是为了钱或名望,而只是因为纯粹的乐趣。”—— Linus Torvalds
2. "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."- Martin Golding
2. “编程的时候,总是想着那个维护你代码的人会是一个知道你住在哪儿的有暴力倾向的精神病患者。”—— Martin Golding
1. “There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.”- C.A.R. Hoare
1. “有两种生成一个软件设计方案的途径。一个是把它做得如此简单,以致于明显不会有漏洞存在。另一个是把它做的如此复杂,以致于不会有明显的漏洞存在。”—— C.A.R. Hoare
来源:http://cnbeta.com/articles/129807.htm
下文列出前10个供读者欣赏。
10. "People think that computer science is the art of geniuses but the actual reality is the opposite, just many people doing things that build on each other, like a wall of mini stones."- Donald Knuth
10. “人们认为计算机科学是天才的艺术,但事实完全相反:只是很多人在共同建立起来的事物之上工作,就像一条由小石头铺成的小径。”—— Donald Knuth
9. “First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack.”- George Carrette
9. “首先学会计算机科学和所有的理论。然后发展出一个编程风格。之后便要忘掉所有这些,以自由的方式探索。”—— George Carrette
8. “Most of you are familiar with the virtues of a programmer. There are three, of course: laziness, impatience, and hubris.”- Larry Wall
8. “大多数的你们都熟悉程序员的美德。它们有三点:懒,不耐烦,以及狂妄自大。”—— Larry Wall
7. “Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other,with no structural integrity, but just done by brute force and thousands of slaves.”- Alan Kay
7. “今日的大多数软件很像埃及金字塔,由千百万砖头堆砌起来,层层相切,没有着整体的结构,是由畜力和成千上万奴隶的力量建立起来的。”—— Alan Kay
6. “The trouble with programmers is that you can never tell what a programmer is doing until it’s too late.”- Seymour Cray
6. “程序员的问题是,不到太晚,你永远无法知道一个他在做着些什么。”—— Seymour Cray
5. “To iterate is human, to recurse divine.”- L. Peter Deutsch
5. “人理解迭代,神理解递归。”—— Peter Deutsch
4. "On two occasions I have been asked [by members of Parliament]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."- Charles Babbage
4. “有两次我被(国会议员)问道:‘ Mr. Babbage,如果你输入计算机错误的数据,正确的答案会出来吗?’我完全无法理解能产生此种问题的大脑的混乱。”
3. "Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program."- Linus Torvalds
3. “大部分好的程序员编程并不是为了钱或名望,而只是因为纯粹的乐趣。”—— Linus Torvalds
2. "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."- Martin Golding
2. “编程的时候,总是想着那个维护你代码的人会是一个知道你住在哪儿的有暴力倾向的精神病患者。”—— Martin Golding
1. “There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.”- C.A.R. Hoare
1. “有两种生成一个软件设计方案的途径。一个是把它做得如此简单,以致于明显不会有漏洞存在。另一个是把它做的如此复杂,以致于不会有明显的漏洞存在。”—— C.A.R. Hoare
来源:http://cnbeta.com/articles/129807.htm