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 ------------------------------------------------- ...
随机推荐
- 【机器学习实战】第5章 Logistic回归(逻辑回归)
第5章 Logistic回归 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/ ...
- C++ 与 Java 语言对比
1 . Java 是完全封装的,而 C++ 的函数是可以定义在 Class 的外部的.从这里就可以看出 C++ 的 OO 思想不够彻底,至少在封装这一点上. 2. C++ 中有拷贝构造函数,可以把一个 ...
- NOIP模拟 最佳序列 - 二分 + 单调队列
题意: 各一个n(\(\le 20000\))的序列,定义纯洁序列为长度len满足\(L \le len \le R\)的序列,纯洁值为某一纯洁序列的平局值,输出所有纯洁序列中最大平均值. 分析: 二 ...
- Activity启动模式需注意的坑
标准启动Standard模式版本差异: 在Lollipop之前,每次以MULTIPLE启动的Activity都会被压入当前任务的顶部,启动 N 次,在当前任务就会出现 N 个Activity的实例,每 ...
- RabbitMQ 延迟队列实现订单支付结果异步阶梯性通知
在第三方支付中,例如支付宝.或者微信,对于订单请求,第三方支付系统采用的是消息同步返回.异步通知+主动补偿查询的补偿机制. 由于互联网通信的不可靠性,例如双方网络.服务器.应用等因素的影响,不管是同步 ...
- setTimeout里的函数是何时进入任务队列里的
先看一段代码 setTimeout(function () { console.log('abc') }, 1000) for (var i = 0; i <= 800000000; i++) ...
- 多域名绑定同一IP地址,Node.js来实现
本来打算用Nginx来实现,看了一会Nginx的配置,感觉又要费时间学习,就抱着试试看的心在网上搜,是否可以用Node.js来实现. 没想到,竟然搜到了.想试一下,但国内域名备案时间长达一个月,我肯定 ...
- 【43.75%】【codeforces 688E】The Values You Can Make
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- WPF--常用布局介绍
概述:本文简要介绍了WPF中布局常用控件及布局相关的属性 1 Canvas Canvas是一个类似于坐标系的面板,所有的元素通过设置坐标来决定其在坐标系中的位置..具体表现为使用Left.Top.Ri ...
- muduo源代码分析--Reactor在模型muduo使用(两)
一. TcpServer分类: 管理所有的TCP客户连接,TcpServer对于用户直接使用,直接控制由用户生活. 用户只需要设置相应的回调函数(消息处理messageCallback)然后TcpSe ...