【版权声明:尊重原创。转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流。请勿用于商业用途】

    其中两个进程通信,有两个过程,以彼此的过程中交换信息,有的都比較复杂,不像上一节那样简单。

普通情况下。存在一个服务进程一直在等待客户进程连接。客户进程和服务进程存在例如以下三种交换数据方式:

客户进程发获取服务进程某一全局数据的请求,服务进程返回该数据(简称get请求);

客户进程发设置服务进程全局数据的请求(简称set请求);

客户进程发设置服务进程全局数据的请求,服务进程设置完毕后返回某一数据,(set与get并存)。

 

这一节我们就来完毕这样一个能够在实际应用中使用的socket进程间通信。

上面所描写叙述的get与set请求可能有非常多种,每一种请求所使用到的数据都不一样。所以我们须要为每一请求定义一个类型,服务进程通过类型能够知道客户进程须要处理什么数据。每个请求服务进程都应当返回其处理的结果返回值。既然是两个进程通信。那么就一定存在数据交换,所以一定存在数据的收发,以及须要知道对端收发数据的大小。所以我们依据这样的须要首先定义两个进程之间交换数据的数据结构(类似于tcp/ip协议数据包格式):

typedef struct _ipc_sock_msg_t {
int msg_type;//请求类型
int msg_rc;//服务进程处理结果的返回值
int msg_buflen;//交换数据的大小
char msg_buf[SOCK_IPC_MAX_BUF];//交换数据的内容
} ipc_sock_msg_t;

服务进程收到客户进程请求之后首先推断请求类型,依据请求类型来进行处理。我们首先定义一个函数数组。在服务进程接收请求之前将要处理的全部请求注冊到该函数数组其中来,收到请求之后依据请求类型索引找到处理函数。

函数数组例如以下:

static int
(*sln_ipc_ser_func[SLN_IPC_MAX_TYPE])(
void *recvbuf, int recv_size,
void *sendbuf, int *send_size);

服务进程接收处理之前先将须要处理的函数注冊到函数数组中,例如以下:

int sln_ipc_ser_func_init(void)
{
int i; for (i = 0; i < SLN_IPC_MAX_TYPE; i++) {
sln_ipc_ser_func[i] = NULL;
} sln_ipc_ser_func[SLN_IPC_TYPE_0x1] = sln_ipc_handle_0x1;
sln_ipc_ser_func[SLN_IPC_TYPE_0x2] = sln_ipc_handle_0x2; return 0;
}

之后服务进程開始监听,等待连接:

监听代码类似上节演示样例:

#if USE_AF_UNIX
fd = sln_ipc_ser_afunix_listen(SOCK_IPC_NAME);
if (fd < 0) {
return -1;
}
#else
fd = sln_ipc_ser_afinet_listen(SOCK_IPC_SER_LISTEN_PORT);
if (fd < 0) {
return -1;
}
#endif

服务进程接收客户进程发送的数据,交给函数sln_ser_handle来处理:

static int
sln_ipc_ser_accept(int listenfd)
{
int connfd;
ssize_t recvlen;
ipc_sock_msg_t recv_msg;
socklen_t addrlen;
#if USE_AF_UNIX
struct sockaddr_un cltaddr;
#else
struct sockaddr_in cltaddr;
#endif addrlen = sizeof(cltaddr);
for (;;) {
connfd = accept(listenfd, (struct sockaddr *)&cltaddr, &addrlen);
if (connfd < 0) {
fprintf(stderr, "accept: %s\n", strerror(errno));
continue;
} if ((recvlen = sln_ipc_recv(connfd, &recv_msg, sizeof(ipc_sock_msg_t))) < 0) {
continue;
} sln_ser_handle(connfd, &recv_msg); close(connfd);
} return 0;
}

当中处理函数sln_ser_handle实现为:

static int
sln_ser_handle(int sockfd, ipc_sock_msg_t *recv_msg)
{
ipc_sock_msg_t send_msg; memset(&send_msg, 0, sizeof(ipc_sock_msg_t)); send_msg.msg_type = recv_msg->msg_type; if ((recv_msg->msg_type >= SLN_IPC_MAX_TYPE)
&& (recv_msg->msg_rc < 0)) {
send_msg.msg_rc = SLN_IPC_RC_TYPE;
} else if (NULL == sln_ipc_ser_func[recv_msg->msg_type]) {
send_msg.msg_rc = SLN_IPC_RC_FUNC;
} else {
send_msg.msg_rc
= sln_ipc_ser_func[recv_msg->msg_type](
recv_msg->msg_buf,
recv_msg->msg_buflen,
send_msg.msg_buf,
&send_msg.msg_buflen);
} if (sln_ipc_send(sockfd, &send_msg, sizeof(ipc_sock_msg_t)) < 0) {
return -1;
} return 0;
}

在函数sln_ser_handle中调用初始化时注冊的服务进程处理函数来完毕客户进程的请求。

初始化注冊的两函数为:

static char     gbuf[256] = "hello, this is server!";

int
sln_ipc_handle_0x1(void *recvbuf, int recv_size, void *sendbuf, int *send_size)
{
printf("=============%s->%d===========\n", __func__, __LINE__);
memcpy(sendbuf, gbuf, strlen(gbuf)); *send_size = strlen(gbuf); return SLN_IPC_RC_OK;
} int
sln_ipc_handle_0x2(void *recvbuf, int recv_size, void *sendbuf, int *send_size)
{
printf("=============%s->%d===========\n", __func__, __LINE__);
memcpy(gbuf, recvbuf, recv_size); *send_size = 0; return SLN_IPC_RC_OK;
}

处理函数带4个參数,分别为:接收数据buffer、接收到的数据大小、发送数据buffer、发送数据大小。当中前两个參数为输入參数,后两个參数为返回输出的參数。服务进程须要依据客户进程发送过来的数据来处理客户请求,然后返回服务进程须要返回的数据以及处理结果(完毕或失败),处理结果在该处理函数的返回值中返回。

以下看看客户进程的实现:

int
sln_ipc_clt_conn(
int msg_type,
int *ret_code,
void *sendbuf,
int sendlen,
void *recvbuf,
int *recvlen)
{
int connfd;
ssize_t ret_size;
socklen_t addrlen;
ipc_sock_msg_t send_msg, recv_msg; #if USE_AF_UNIX
if ((connfd = sln_ipc_clt_afunix_conn_init(SOCK_IPC_NAME)) < 0) {
return -1;
}
addrlen = sizeof(struct sockaddr_un);
#else
if ((connfd = sln_ipc_clt_afinet_conn_init(SOCK_IPC_SER_LISTEN_PORT)) < 0) {
return -1;
}
addrlen = sizeof(struct sockaddr_in);
#endif if (connect(connfd, (struct sockaddr *)&seraddr, addrlen) < 0) {
fprintf(stderr, "connect: %s\n", strerror(errno));
return -1;
} memset(&send_msg, 0, sizeof(ipc_sock_msg_t));
send_msg.msg_type = msg_type;
if (NULL != sendbuf) {
send_msg.msg_buflen = sendlen;
memcpy(send_msg.msg_buf, sendbuf, sendlen);
}
if ((ret_size = ipc_send(connfd, &send_msg, 3 * sizeof(int) + sendlen)) < 0) {
return -1;
} if ((ret_size = ipc_recv(connfd, &recv_msg, sizeof(ipc_sock_msg_t))) < 0) {
return -1;
} if (recv_msg.msg_type != send_msg.msg_type) {
printf("Error msg type!\n");
return -1;
} *ret_code = recv_msg.msg_rc;
if (NULL != recvbuf) {
*recvlen = recv_msg.msg_buflen;
memcpy(recvbuf, recv_msg.msg_buf, recv_msg.msg_buflen);
} return 0;
}

客户进程调用的接口的实现起来比較简单。仅仅须要告知服务进程我请求的处理类型(msg_type),以及须要传输的数据(sendbuf)及大小(sendlen),服务进程会返回处理结果(ret_code)以及返回数据(recvbuf)和大小(recvlen)。

本节演示样例源代码:

http://download.csdn.net/detail/gentleliu/8140479

版权声明:本文博主原创文章,博客,未经同意不得转载。

假设你认为你的实际物品。请点击以下“最佳”。

阐述linux IPC(两):基于socket进程间通信(下一个)的更多相关文章

  1. 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室

    原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  2. 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室

    原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  3. Linux IPC tcp/ip socket 编程

    模型 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include < ...

  4. Linux CFS调度器之pick_next_task_fair选择下一个被调度的进程--Linux进程的管理与调度(二十八)

    1. CFS如何选择最合适的进程 每个调度器类sched_class都必须提供一个pick_next_task函数用以在就绪队列中选择一个最优的进程来等待调度, 而我们的CFS调度器类中, 选择下一个 ...

  5. 阐述linux IPC(五岁以下儿童):system V共享内存

    [版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途]         system V共享内存和posix ...

  6. Linux IPC udp/ip socket 编程

    模型 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include < ...

  7. 基于Socket网络编程

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a2011480169/article/details/73602708 博客核心内容: 1.Sock ...

  8. Leetcode 503. 下一个更大元素 II

    1.题目描述 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应 ...

  9. C语言 linux环境基于socket的简易即时通信程序

    转载请注明出处:http://www.cnblogs.com/kevince/p/3891033.html      ——By Kevince 最近在看linux网络编程相关,现学现卖,就写了一个简易 ...

随机推荐

  1. 产品经理(五岁以下儿童)myVegas Slots排名上升的秘密

    myVEGAS Slots于AppStore上排名在今年也就是2月份时候飙升,那么什么情况导致这个现象的呢,我们试图通过App Annie的分析给出答案. 上面是myVegas的排名情况,我们能够看到 ...

  2. [TWRP 2.8.4 ] 小米 3W 中文-英文版本 twrp

    经过半个小时的代码修改,从 2.7.0 移植到 2.8.4 的源代码上. 汉化操作是使用切换语言选项来实现的. 注意: 此版本的 twrp 还不支持双系统切换功能. 作者:laser杨万荣 如果需要转 ...

  3. 重新想象 Windows 8 Store Apps (23) - 文件系统: 文本的读写, 二进制的读写, 流的读写, 最近访问列表和未来访问列表

    原文:重新想象 Windows 8 Store Apps (23) - 文件系统: 文本的读写, 二进制的读写, 流的读写, 最近访问列表和未来访问列表 [源码下载] 重新想象 Windows 8 S ...

  4. centos7关闭防火墙(转)

    直接命令:service firewalld stop 1. Disable Firewalld Service. [root@rhel-centos7-tejas-barot-linux ~]# s ...

  5. 【原创】leetCodeOj ---Remove Duplicates from Sorted List II 解题报告

    明日深圳行,心情紧张,写博文压压惊 囧 ------------------------------------- 原题地址: https://oj.leetcode.com/problems/rem ...

  6. Cocos2d-x示例:单点触摸事件

    为了让大家掌握Cocos2d-x中的事件机制,以下我们以触摸事件为例.使用事件触发器实现单点触摸事件.该实比如图8-3所看到的,场景中有三个方块精灵,显示顺序如图8-3所看到的,拖拽它们能够移动它们. ...

  7. .Net中获取打印机的相关信息

    原文:.Net中获取打印机的相关信息 新项目中牵涉到对打印机的一些操作,最重要的莫过于获取打印机的状态,IP等信息,代码量不大,但是也是自己花了一点时间总结出来的,希望能帮助需要的朋友. Printe ...

  8. Lua 脚本语法说明(转)

    Lua脚本语法说明(增加lua5.1部份特性) Lua 的语法比较简单,学习起来也比较省力,但功能却并不弱. 所以,我只简单的归纳一下Lua的一些语法规则,使用起来方便好查就可以了.估计看完了,就懂得 ...

  9. C3P0具体的配置说明(com.mchange.v2.c3p0.ComboPooledDataSource)

    C3P0它是一个开源JDBC连接池,它lib文件夹和Hibernate一起公布,包含了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对 ...

  10. 玩转Web之easyui(一)-----easy ui datagird 分页

    easy ui 中数据表格的分页其实是很简单的,分页是在数据表格可以正常显示数据的基础上进行的,在这里给出servlet的代码,其中selectAll()方法是从数据库中提取所有数据, 分页的一种思路 ...