网络应用程序设计(方敏)-第5章 进程间通信及实现方法
通信行业-西安邮电大学Linux高级编程进程间通信 精品

2021/8/6
11
消息队列属性
2021/8/6
12
消息struct msg结构体
//come from /usr/src/kernels/’uname –r’/inlcude/linux/msg.h /*one msg_msg structure for each message */ struct msg_msg{
2021/8/6
5
例:ftok的使用
#include <stdio.h> #include <sys/types.h> main(){
key_t key; key=ftok(".",1); printf("the key is %x\n",key); }
2021/8/6
人民邮电出版社出版 杨宗德编著
struct list_head m_list; long m_type; int m_ts; /*message test size */ struct msg_msgseg* next; void * security; /* the actual message follows immediately */ };
printf("file st_ino=%x\n",buf.st_ino);
printf("number=%x\n",i);
key=ftok(argv[1],i);
printf("key=0x%x ",key);}
网络应用程序设计(方敏 西电版)第4章 进程与信号机制

(5) SIGFPE:由某种硬件条件而产生,此信号表示浮点 溢出和一些整数算术运算条件的满足,如被零除。
(6) SIGHUP:当一个终端关闭时,所有以该终端为控 制终端的进程均收到这个信号。当进程组头发出该信号时, 该进程组中的所有进程接收到这个信号。
(2) SIGBUS:由硬件故障错误产生。
(3) SIGCHLD:进程结束时向其父进程发送的信号,
若父进程未收到此信号,该信号便被丢掉。该信号还
可以表示子进程的状态变化,它可以表示子进程结束,
也可以表示子进程被信号
SIGSTOP、SIBTTIN、
SIGTTOU、SIGTSTP中断。
第4章 进程与信号机制
第4章 进程与信号机制
4.2.5 设置进程对信号的响应 如果进程要处理某一信号,那么就要在进程中设
置该信号的关联动作或称对信号的响应、安装信号。 设置信号的关联动作主要用来确定信号值以及进程针 对该信号值与动作之间的映射关系,也就是说,进程 将要处理该信号;该信号被传递给进程时,将执行何 种操作。
这些由终端产生的信号一般由内核发送给进程, 不只发给正在运行的进程,也发给所有终端控制组中 的进程。
第4章 进程与信号机制
(4) 在陷入处理子程序TRAP中,针对各种故障以 及使用的各种陷入指令产生不同类型的信号,如 SIGEMT为终止并保留存储映像,SIGFPE为浮点算术 错信号。
(5) 某些软件条件也产生信号。例如,一个加急数 据到达管套时,将产生SIGURG信号。
(1) 当一个信号发出之后,要保证信号管理函数装 入,这就意味着用户信号管理函数能够再次调用 SIGNAL产生某个信号之前,如果有同一信号出现就会 丢失。
网络应用程序设计(方敏 西电版)第2章 基于TCP套接字的编程

X25
X25
这些类型的套接字代表各种不同的连接服务。
第2章 基于TCP套接字的编程
Linux的BSD 套接字支持下面的几种套接字类型: (1) 流式(stream)。这种套接字提供了可靠的双向顺序数 据流连接。它可以保证数据传输中的完整性、正确性和单 一性。INET寻址簇中的TCP协议支持这种类型的套接字。 (2) 数据报(datagram)。这种类型的套接字也可以像流式 套接字一样提供双向的数据传输,但它们不能保证传输的 数据一定能够到达目的节点,也无法保证到达数据以正确 的顺序到达以及数据的单一性、正确性。UDP协议支持这 种类型的套接字。
第2章 基于TCP套接字的编程
网络应用程序设计(方敏 西电版) 第2章 基于TCP套接字的编程
第2章 基于TCP套接字的编程
2.1 概述
20世纪80年代早期,美国国防高级研究计划局(ARPA, Advanced Research Projects Agency)资助了加利福尼亚大学伯 克利分校一个研究组,将TCP/IP 软件移植到UNIX操作系统 中,并将结果提供给其他网点。作为项目的一部分,设计者 们希望像访问文件一样去访问网络,因此,创建了一个接口, 应用进程使用这个接口可以方便的进行通信。为了支持 TCP/IP功能增加的新系统调用接口,形成了Berkeley Socket, 这个系统被称为Berkeley UNIX或BSD UNIX(TCP/IP首次出 现 在 BSD 4.1 版 本 (release 4.1 of Berkeley Software Distribution))。由于许多计算机厂商都采用了Berkeley UNIX, Socket得到了迅速普及并被广泛使用。
(5) 由于<linux/in.h>和<linux/socket.h>是Linux特有的 头文件,为了能够保持代码的可移植性,在程序中不要直 接 包 含 它 们 , 而 与 平 台 无 关 的 <netinet /in.h> 、 <sys/ socket.h>包含了它们。因此,程序中应该包含这两个头文 件。
VC_进程间通信

//--------------------------------------------------------------------
void CDataSendDlg::OnSendRegmsg()
{????????????????????????????? // 更新数据
void CDataRecvDlg::OnRegReceiveMsg(WPARAM wParam,LPARAM lParam)
{
// 增加用户自定义程序代码
…
}
其中OnUserReceiveMsg()函数为WM_COMM消息的映射函数,OnRegReceiveMsg()函数为wm_nRegMsg消息的映射函数。可以看出,这两种消息的映射函数形式是一样的。
在接收消息的程序中,除与发送消息的程序需要定义相同的消息外,还需要定义相应的消息映射和消息映射函数,消息的映射方法如下:
ON_MESSAGE(WM_COMM,OnUserReceiveMsg)
ON_REGISTERED_MESSAGE(wm_nRegMsg,OnRegReceiveMsg)
与以上消息映射对应的函数定义如下:
l?????? 间接通信:借助于收发双方进程之外的共享数据结构作为通信中转,如剪贴板。通常接收和发送方的数目可以是任意的。
(3)本地通信和远程通信
l?????? 本地通信方式:这种通信又称之为同机通信,它是在同一台计算机上的程序之间进行的,也就是说客户进程和服务进程位于同一台计算机上。
l?????? 远程通信方式:这种通信又称之为网间的进程通信,要解决的是不同主机进程间的相互通信问题(可把同机进程通信看作是其中的特例)。在这种通信中,首先要解决的是网络间的进程标识问题。同一主机上,不同进程可用进程号(process ID)唯一标识。但在网络环境下,各主机独立分配的进程号不能唯一标识该进程。例如,主机A赋予某个进程号5,在B机中也可以存在5号进程,因此,“5号进程”这句话就没有意义了。其次,操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同。因此,网间的进程通信还要解决多重协议的识别问题。
网络程序设计教材第六章 机内进程间通信

第六章机内进程间通信6.1 引言计算机网络通信通常包括广播通信、多播通信和点对点通信。
一个基于网络的软件系统,从通信进程的物理位置来看,系统中的进程通信通常包括两种方式,即位于不同节点上的进程通信和一个节点上不同进程之间的通信。
对于不同节点上的进程通信,主要采用Internet 域套接字技术实现;对于一个节点上不同进程之间的通信,绝大多数操作系统提供了管道、共享内存、套接字方法。
对于许多网络应用系统,例如入侵检测系统(IDS)、网管系统等,系统要求很高的实时性,通信性能的好坏直接决定了该系统的可用性和效率。
其中一个节点上的进程之间通信通常占有很大比重,因此,对于一个节点上不同进程之间的通信性能进行研究是十分重要的。
网络编程通常涉及多个进程之间相互作用,相互协调它们的活动。
这一协调是通过进程间的某些主动或被动通信实现的。
Linux系统提供多种在一个节点上进程间通信方式,主要有信号(Signal)、管道(pipe)、命名管道(FIFOS)、消息队列(message queue)、信号灯(semaphore)、共享内存(shared memory)和内存映象(memory mapped file)以及UNIX 域类型的套接字。
信号是UNIX系统中最原始的进程间同步和通信的工具,用于通知进程在它的运行环境中发生的事件,这种通信方式主要用于传输少量数据。
消息队列和共享内存是同一计算机内进程间通信的重要方式,消息队列支持多路复用,但需要进行两次数据的复制,从用户空间到核心,再从核心到用户空间;共享内存不需要多次拷贝,所以在传输数据量大的进程通信中,使用共享内存比使用消息队列性能好。
对于使用Internet域的套接字,既可以支持机内进程间通信,也可以支持不同机器之间进程通信,有关文献指出,对于本地通信,采用UNIX域套接字的通信速度是采用Internet 域套接字的2倍. 因此,使用UNIX域套接字支持位于同一个节点上的进程间通信。
网络应用程序设计(方敏 西电版)第3章 UDP套接字与原始套接字的编程

第3章 UDP套接字与原始套接字的编程
for(;;) {
n=recvfrom(sockfd , msg , 1024 , 0 , (struct sockaddr*)&addr,&addrlen); /* 响应客户机请求 */ sendto(sockfd,msg,n,0,addr,addrlen); } }
第3章 UDP套接字与原始套接字的编程
(4) 发送数据时需指定接收方的地址。UDP套接字 是面向无连接的套接字的,所以在套接字数据结构中 不会保存接收方的IP地址及其端口号。如果应用程序 要发送数据,就需要在调用发送函数sendto的同时指定 接收方的地址。当应用程序接收数据报时,如果需要 知道发送者的地址,则可以在调用接收函数recvfrom中 提供空间由内核来填充;如果不关心对方的地址,则 可以将函数recvfrom的参数from设置为空指针NULL, 同时也必须将参数addrlen设置为NULL。
re c vfrom 阻塞,等待客户机请求
请求数据报 处理客户机数据报
b in d s e n d to
s e n d to
服务器响应 数据报
re c vfrom
c lo se
图3-1 UDP客户机/服务器程序的编程模型
第3章 UDP套接字与原始套接字的编程
在前面的章节中,已经介绍了基于TCP套接字编程的 函数调用模型,比较TCP和UDP编程模型可以看出,UDP 协议不需要事先在客户机、服务器程序之间建立连接。服 务 器 端 在 调 用 socket 函 数 生 成 一 个 UDP 套 接 字 后 , 利 用 bind函数将套接字与本地IP、端口号绑定,然后,服务器 端调用recvfrom函数等待接收由客户端发送来的数据。客 户机首先调用socket函数创建一个UDP套接字,然后利用 sendto函数将请求包发送至服务器端;服务器端收到请求 包后,根据请求进行处理,调用sendto函数将处理结果作 为应答数据发送给客户机。客户机调用recvfrom函数接收 服务器端发送来的应答数据。当通信结束后,客户机调用 close函数关闭UDP套接字,而服务器端可以保留已建立的 UDP套接字继续与其他客户机进行数据通信。
网络编程实用教程第二版_第5章

//请求连接到服务器 sockClient.Connect(strAddr, nport);
5.1.2 创建CasyncSocket类对象
本书将CAsyncSocket类对象称为异步套接字对象。创建异 步套接字对象一般分为两个步骤,首先构造一个CAsyncSocket
对象,再创建该对象的底层的SOCKET句柄。
#define FD_CONNECT
#define FD_CLOSE
0x10
0x20
5.1.3 关于CAsyncSocket类可以接受并处理的消息事件 他们代表MFC套接字对象可以接受并处理的六种网络事 件,当事件发生时,套接字对象会收到相应的通知消息,并 自动执行套接字对象响应的事件处理函数。 (1)FD_READ事件通知:通知有数据可读。 (2)FD_WRITE事件通知:通知可以写数据。 (3)FD_ACCEPT事件通知:通知监听套接字有连接请 求可以接受。
virtual BOOL Accept( CAsyncSocket& rConnectedSocket,
SOCKADDR* lpSockAddr = NULL, int* lpSockAddrLen = NULL );
第5章 MFC WinSock类的编程
5.1 CAsyncSocket类 5.2 CSocket类 5.3 CSocket类的编程模型 5.4 用CAsyncSocket类实现聊天室程序 5.5 用CSocket类实现聊天室程序
1
第5章 MFC Winsock类的编程
为简化套接字网络编程,更方便地利用Windows 的消息驱动机制,微软的基础类库(Microsoft
virtual void OnOutOfBandData(int nErrorCode);
网络应用程序的设计第5章 进程间通信及实现方法.ppt

}
}
第5章 进程间通信及实现方法
运行结果 child process: the datas from parent. parent process: the datas from child. 程序中信息的传输过程如图5-2所示。
第5章 进程间通信及实现方法
chpipe1
chpipe1[1] 父进程
第5章 进程间通信及实现方法
(2) 接收进程从信道按需取用信息,不必考虑长度 限制。
(3) 发送和接收进程的实施相互协调,其中发送和 接收进程相互协调指的是:
① 发送和接收进程对通信信道的使用是互斥的, 一个进程利用信道进行读或写操作时,其他进程就不 能用,当这个进程不用信道时,其他的进程才能使用。
第5章 进程间通信及实现方法
第5章 进程间通信及实现方法
5.1 管道 5.2 命名管道 5.3 消息通信 5.4 共享内存 5.5 信号灯 5.6 UNIX域套接字 习题
第5章 进程间通信及实现方法
5.1 管道
1. 管道的定义 Linux系统提供了几种通信方式,如消息队列、信 号量及共享内存等。它们有的需要使用较多的存储资 源才能进行信息传递,有的不适合在进程间进行大量 的信息传递。而管道机构能够为进程之间大量信息的 传输提供通道。管道是Linux系统利用文件系统为基础 构成的一种进程间通信的机构。它有以下几个特点: (1) 管道是一个单向的通信信道,发送进程能以比 较简单的方式,把要发送的信息以信息流的方式写入 信道,不需要考虑对每次传送信息长度的限制。
else
printf("parent process:%s\n",buff);
} /* fork */
第5章 进程间通信及实现方法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第5章 进程间通信及实现方法
{ char parstr[]={"parfile.dat"}; int n; char buff[100]; n=strlen(parstr); if (write(wfd,parstr,n)!=n) err_sys("client: send error"); if (read(rfd,buff,100)<=0) err_sys("client: receive error"); else printf("parent process:%s\n",buff);
err_sys("receive error");
else
printf("parent process:%s\n",buff);
} /* fork */
第5章 进程间通信及实现方法
else { close(chpipe1[1]); 中 */
/* 在子进程
close(chpipe2[0]);
if (read(chpipe1[0],buff,100)<=0)
}
}
第5章 进程间通信及实现方法
程序pro_client中的父进程通过管道发送文件名给 子进程,pro_server中的子进程通过管道读文件名,如 果接收的文件名有错,文件打不开,则将错误信息回传 给client方(父进程);否则,读文件中的信息并将文件 信息回传给client。
利用管道的只能在父子进程间的通信,对于两个完 全不相关的进程不能采用管道进行通信,这是管道的一 个特点。
if (pipe(chpipe1)<0) err_sys("pipe1 creat error");
if (pipe(chpipe2)<0) err_sys("pipe2 creat error");
if (fork()) { /*在父进程中 */ close(chpipe1[0]); close(chpipe2[1]);
err_sys("receive error");
else
buff);
printf("child process : %s\n" ,
if (write(chpipe2[1] , chistr , sizeof(chistr))!=sizeof(chistr))
err_sys("send error");
当需要进行双向数据传输时,必须建立两 个管道。每个管道负责一个方向的数据传输。它的操作过 程如下:
● 创建两个管道:管道1和管道2; ● 调用fork()产生子进程; ● 父进程关闭管道1的读端;
第5章 进程间通信及实现方法
● 父进程关闭管道2的写端;
● 子进程关闭管道1的写端;
● 子进程关闭管道2的读端。
父进程
chpipe1[1]
chpipe2
chpipe1[0]
chpipe2[0]
chpipe2[1]
子进程
图5-2 利用管道进行通信
第5章 进程间通信及实现方法
首先,进程创建两个管道chpipe1和chpipe2,然后利 用 fork 产生一子进程。如果子进程创建成功,父进程利 用管道chpipe1[1]作写入端,用管道chpipe2[0]作读出端, 关 闭 管 道 端 chpipe1[0] 和 chpipe2[1] 。 子 进 程 用 管 道 chpipe1[0]作为读出端,用管道chpipe2[1]作为写入端, 关闭管道端chpipe1[1]和chpipe2[0],两者进行通信。就 每个管道而言,均是单向管道,其数据信息只按一个方向 流动。就每个进程而言,信息的传送是双向的,即能发送 又能接收。
① 发送和接收进程对通信信道的使用是互斥的,一 个进程利用信道进行读或写操作时,其他进程就不能用, 当这个进程不用信道时,其他的进程才能使用。
② 发送和接收进程都能了解对方是否存在。 ③ 发送和接收进程同步。即接收进程在信道中已有 信息时,才接收信息;发送进程要在信道空闲时,才能 发送信息。
第5章 进程间通信及实现方法 管道是由系统调用pipe建立的,其调用格式为: #include <unistd.h> int pipe(int fd[2]); 参数fd指向两个文件描述符;fd[0]返回管道
}
第5章 进程间通信及实现方法
else { while ((n=read(fd,buff,1024))>0)
if(wirte(wfd,buff,n)!=n)
error");
err_sys("server : message send
if (n<0)
err_sys("server:read error");
读通道打开的文件号,用于读;fd[1]返回管道的写通道 打开的文件号,用于写,如图5-1所示。
第5章 进程间通信及实现方法
write
fd[1]
管道
fd[0]
read
图5-1 管道工作示意图
第5章 进程间通信及实现方法
2.管道的共享使用 进程利用pipe系统调用生成管道后,通常接着就要创 建一个或几个子进程,管道被父子进程共享。每个进程可 以用类似文件读写操作方式对管道进行存取操作。一般情 况下,一个管道最好为两个进程专用,一个进程只用其发 送端,另一个进程只用其接收端。
第5章 进程间通信及实现方法
5.2 命名管道
命名管道与管道不同之处在于,它与一个路径名关 联,以FIFO的文件形式存在于文件系统中。这样,即使 与FIFO的创建进程无亲缘关系的进程,只要可以访问该 路径,就能够彼此通过FIFO相互通信。
系统调用mkfifo() 创建命名管道: int mkfifo(const char * pathname , mode_t mode);
下面的例子说明了管道机构的建立和使用。
main()
{
char parent.\n"};
parstr[]={"the
datas
char child.\n"};
chistr[]={"the
datas
int chpipe1[2], chpipe2[2];
char buff[100];
from from
第5章 进程间通信及实现方法
第5章 进程间通信及实现方法 if ((pid=fork())<0) { err_sys("can't fork");} else if (pid) { /* 在父进程中 */ close(chpipe1[0]); close(chpipe2[1]); pro_client(chpipe2[0],chpipe1[1]);
第5章 进程间通信及实现方法
第5章 进程间通信及实现方法
5.1 管道 5.2 命名管道 5.3 消息通信 5.4 共享内存 5.5 信号灯 5.6 UNIX域套接字 习题
第5章 进程间通信及实现方法
5.1 管道
1. 管道的定义 Linux系统提供了几种通信方式,如消息队
列、信号量及共享内存等。它们有的需要使用较多的存 储资源才能进行信息传递,有的不适合在进程间进行大 量的信息传递。而管道机构能够为进程之间大量信息的 传输提供通道。管道是Linux系统利用文件系统为基础构 成的一种进程间通信的机构。它有以下几个特点:
如果将上面程序改为在顾客—服务员模式上运行,上 例程序可改写为:由main()产生一管道,然后产生一个子 进程。原进程运行顾客程序,而子进程运行服务员程序。
第5章 进程间通信及实现方法 main() { int chpipe1[2], chpipe2[2]; int pid; if (pipe(chpipe1)<0) err_sys("pipe1 creat error"); if (pipe(chpipe2)<0) err_sys("pipe2 creat error");
}
第5章 进程间通信及实现方法 服务员子程序为: #include <stdlio.h> pro_server(rfd, wfd) int rfd; int wfd; { int n; char buff[1024], errbuff[64]; int n, fd;
第5章 进程间通信及实现方法
/* 从 IPC 描述符中读文件名 */ if ((n=read(rfd,buff,1024))<=0)
第5章 进程间通信及实现方法
if
(write(chpipe1[1] , parstr ,
sizeof(parstr))!=sizeof(parstr))
err_sys ("send error");
close (chpipe1[1]);
if (read(chpipe2[0],buff,100)<=0)
close (chpipe2[1]);
}
第5章 进程间通信及实现方法
运行结果 child process: the datas from parent. parent process: the datas from child. 程序中信息的传输过程如图5-2所示。
第5章 进程间通信及实现方法
chpipe1
第5章 进程间通信及实现方法
该函数的pathname是一个路径名,也就是创建后命 名管道的名字,mode打开文件的模式,与打开普通文件 的open()函数中文件操作模式参数相似。如果mkfifo的 第一个参数是一个已经存在的路径名时,则返回类型为 EEXIST 的 错 误 ; 如 果 返 回 该 错 误 , 那 么 只 要 调 用 打 开 FIFO的函数就可以了。生成了命名管道后,就可以使用 一般的文件I/O函数如open、close、read、write等来对 它进行操作。