Linux下C语言RPC(远程过程调用)编程实例
在查看libc6-dev软件包提供的工具(用 dpkg -L libc6-dev 命令)的时候,发现此软件包提供了一个有用的工具rpcgen命令。
通过rpcgen的man手册看到此工具的作用是把RPC源程序编译成C语言源程序,从而轻松实现远程过程调用。
下面的例子程序的作用是客户端程序取中心服务器上时间的,编程过程如下:
先编写一个 “ RPC 语言 ” ( RPC Language ( Remote Procedure Call Language ) ) 的源文件 test.x ,文件后缀名为 x 。
源代码如下:
| program TESTPROG { version VERSION { string TEST(string) = 1; } = 1; } = 87654321; |
说明:这里数字87654321是RPC程序编号,还有VERSION版本号为1,都是给RPC服务程序用的。同时指定程序接受一个字符串参数。
运行这个命令:
| rpcgen test.x |
将生成三个源文件:
| test_clnt.c test.h test_svc.c |
源文件test_clnt.c 内容如下:
| /* * Please do not edit this file. * It was generated using rpcgen. */ #include <memory.h> /* for memset */ /* Default timeout can be changed using clnt_control() */ char ** memset((char *)&clnt_res, 0, sizeof(clnt_res)); |
说明:这是一个客户端调用函数,即客户端代码需要用到此函数。
源文件test.h内容如下:
| /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _TEST_H_RPCGEN #include <rpc/rpc.h> #ifdef __cplusplus #define TESTPROG 87654321 #if defined(__STDC__) || defined(__cplusplus) #else /* K&R C */ #ifdef __cplusplus #endif /* !_TEST_H_RPCGEN */ |
说明:这里定义了一些公用头文件。
源文件test_svc.c内容如下:
| /* * Please do not edit this file. * It was generated using rpcgen. */ #include "test.h" #ifndef SIG_PF static void switch (rqstp- case NULLPROC: case TEST: default: int pmap_unset (TESTPROG, VERSION); transp = svcudp_create(RPC_ANYSOCK); transp = svctcp_create(RPC_ANYSOCK, 0, 0); svc_run (); |
说明:这是一个标准的服务器端代码。
运行下列命令生成一个客户端源文件test_client.c:
| rpcgen -Sc -o test_client.c test.x |
源代码test_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 "test.h" void #ifndef DEBUG result_1 = test_1(&test_1_arg, clnt); int if (argc > 2) { |
运行这个命令生成服务端源文件test_srv_func.c:
| rpcgen -Ss -o test_srv_func.c test.x |
源文件test_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 "test.h" char ** /* return &result; |
说明:这是一个服务器端调用的函数。
至此,我们就可以编译生成程序来运行了。
用下面的命令编译生成服务端程序test_server:
| gcc -Wall -o test_server test_clnt.c test_srv_func.c test_svc.c |
用下面的命令编译生成客户端程序test_client:
| gcc -Wall -o test_client test_client.c test_clnt.c |
运行下列命令启动服务端:
| ./test_server |
运行下列命令可以进行客户端测试:
| ./test_client 127.0.0.1 |
但是由于现的的服务端没有处理客户端请求,所以这样的程序还不能完成任何工作。
下面我们先给服务端程序加上代码,使这个服务器能完成一定的工作。即修改 test_srv_func.c ,在 “ * insert server code here ” 后面加上取时间的代码,即修改后的 test_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 <time.h> #include "test.h" char ** /* return &result; |
再修改客户端代码以显示服务器端返回的内容,即修改test_client.c源文件,只需要修改其中的函数testprog_1,修改后如下:
| void testprog_1(char *host) { CLIENT *clnt; char * *result_1; char * test_1_arg; test_1_arg = (char *)malloc(128); result_1 = test_1(&test_1_arg, clnt); |
重新运行上述编译命令编译生成程序:
| gcc -Wall -o test_server test_clnt.c test_srv_func.c test_svc.c gcc -Wall -o test_client test_client.c test_clnt.c |
启动服务端程序后运行客户端程序如下:
| ./test_client 127.0.0.1 收到消息 ... 服务器当前时间是 :Tue Feb 27 11:45:21 2007 |
为了省略每次输入gcc命令的麻烦,也为了维护我们的工程,可以运行下列命令生成一个Makefile文件:
| rpcgen -Sm test.x > Makefile |
生成的Makefile内容如下:
| # This is a template Makefile generated by rpcgen
# Parameters CLIENT = test_client SOURCES_CLNT.c = TARGETS_SVC.c = OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o) CFLAGS += -g # Targets all : $(CLIENT) $(SERVER) $(TARGETS) : $(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) $(SERVER) : $(OBJECTS_SVC) clean: |
由于我们手工生成了源文件,所以要修改一下这个Makefile,修改后如下:
| # This is a template Makefile generated by rpcgen
# Parameters CLIENT = test_client SOURCES_CLNT.c = TARGETS_SVC.c = test_clnt.c test_srv_func.c test_svc.c OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o) CFLAGS += -g # Targets all : $(CLIENT) $(SERVER) $(TARGETS) : $(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) $(SERVER) : $(OBJECTS_SVC) clean: |
转自:http://blog.csdn.net/hitxiaotao/article/details/2267523
http://blog.csdn.net/iw1210/article/details/41051779
Linux下C语言RPC(远程过程调用)编程实例的更多相关文章
- Linux下C语言的socket网络编程
关于详细的服务器建立的步骤以及相关的socket套接字的知识我已经在python socket编程的文章中提到过了,大家可以参看那一篇博客来历接socket套接字编程的内容,由于要是用C相关的API所 ...
- Linux下C语言的进程控制编程
代码: #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/ty ...
- Linux下C语言编程实现spwd函数
Linux下C语言编程实现spwd函数 介绍 spwd函数 功能:显示当前目录路径 实现:通过编译执行该代码,可在终端中输出当前路径 代码实现 代码链接 代码托管链接:spwd.c 所需结构体.函数. ...
- Linux基础与Linux下C语言编程基础
Linux基础 1 Linux命令 如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 登录Linux后,我们就可以在#或$符后面去输入命令,有 ...
- LINUX下C语言编程基础
实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...
- LINUX下C语言编程调用函数、链接头文件以及库文件
LINUX下C语言编程经常需要链接其他函数,而其他函数一般都放在另外.c文件中,或者打包放在一个库文件里面,我需要在main函数中调用这些函数,主要有如下几种方法: 1.当需要调用函数的个数比较少时, ...
- linux下C语言多线程编程实例
用一个实例.来学习linux下C语言多线程编程实例. 代码目的:通过创建两个线程来实现对一个数的递加.代码: //包含的头文件 #include <pthread.h> #include ...
- Linux下C语言编程基础学习记录
VIM的基本使用 LINUX下C语言编程 用gcc命令编译运行C语言文件 预处理阶段:将*.c文件转化为*.i预处理过的C程序. 编译阶段:将*.i文件编译为汇编代码*.s文件. 汇编阶段:将*.s ...
- 【转】Linux基础与Linux下C语言编程基础
原文:https://www.cnblogs.com/huyufeng/p/4841232.html ------------------------------------------------- ...
随机推荐
- Android 自动弹出软键盘(输入键盘)
很多应用中对于一个界面比如进入搜索界面或者修改信息等等情况,为了用户体验应该自动弹出软键盘而不是让用户主动点击输入框才弹出(因为用户进入该界面必然是为了更改信息).具体实现这种效果如下: EditTe ...
- ajax 发送请求无法重定向问题
原因: ajax请求默认就是不支持重定向的,因为它是局部刷新,不重新加载页面. 解决方案: 开发中需要多处使用重定向的情况下,大多都是在Spring mvc 的拦截器中,或过滤器中使用,此方法是在sp ...
- phpStorm怎么解决502 bad gateway(总结整理)
phpStorm怎么解决502 bad gateway(总结整理) 一.总结 1.配置 php解释器. 二.phpStorm解释器与服务器配置(解决502 bad gateway与404 not fo ...
- 【codeforces 765D】Artsem and Saunders
[题目链接]:http://codeforces.com/contest/765/problem/D [题意] 给你一个函数f(x); 要让你求2个函数g[x]和h[x],使得g[h[x]] = x对 ...
- MySQL执行计划分析
原文:MySQL执行计划分析 一. 执行计划能告诉我们什么? SQL如何使用索引 联接查询的执行顺序 查询扫描的数据函数 二. 执行计划中的内容 SQL执行计划的输出可能为多行,每一行代表对一个数据库 ...
- 高并发场景之RabbitMQ
高并发场景之RabbitMQ 上次我们介绍了在单机.集群下高并发场景可以选择的一些方案,传送门:高并发场景之一般解决方案 但是也发现了一些问题,比如集群下使用ConcurrentQueue或加锁都不能 ...
- HSSFWorkBooK用法 ---Excel表的导出和设置
public ActionResult excelPrint() { HSSFWorkbook workbook = new HSSFWorkbook();// 创建一个Excel文件 HSSFShe ...
- opencc 繁体简体互转 (C++)
繁体字通常采用BIG5编码,简体字通常采用GBK或者GB18030编码,这种情况下,直接使用iconv(linux下有对应的命令,也有对应的C API供编程调用)就行.对于默认采用utf-8 ...
- WPF 高速书写 StylusPlugIn 原理
原文:WPF 高速书写 StylusPlugIn 原理 本文告诉大家 WPF 的 StylusPlugIn 为什么能做高性能书写,在我的上一篇博客和大家介绍了 WPF 的触摸原理,但是没有详细告诉大家 ...
- ASP.Net请求小周期
另一篇另篇2 ASP.NET请求处理全过程 一个ASP.NET请求过程中,从浏览器中发出一个Web请求 到 这个请求被响应并显示在浏览器中的过程中究竟会发生哪些不同的事件,当我们进入这个事件之旅时,我 ...