操作系统-进程通信(信号量、匿名管道、命名管道、Socket)
进程通信(信号量、匿名管道、命名管道、Socket)
具体的概念就没必要说了,参考以下链接。
Source Code:
1. 信号量(生产者消费者问题)
#include <iostream>
#include <Windows.h>
#include <process.h>
#include <vector>
using namespace std; #define STD _stdcall //被调用者负责清栈
int BufferSize; //缓冲区大小 CRITICAL_SECTION CR; //临界区
HANDLE Empty = NULL; //信号量:空闲缓冲区
HANDLE Full = NULL; //信号量:满缓冲区
vector<int>Buffer; //缓冲区 /*生产者线程*/
DWORD STD Producer(void *lp)
{
while(true)//自旋测试
{
//等待空缓冲区:P(empty)
WaitForSingleObject(Full, INFINITE);//一直等待
//进入缓冲区P(mutex)
EnterCriticalSection(&CR);
//生产数据
int s = rand()%;
Buffer.push_back(s);
cout << "Producer produces an element : " << s <<endl;
//退出缓冲区V(mutex)
LeaveCriticalSection(&CR);
//增加满缓冲区V(full)
ReleaseSemaphore(Empty, , NULL);
//睡一会儿
Sleep();
}
} /*消费者线程*/
DWORD STD Consumer(void *lp)
{
while(true)//自旋测试
{
//等待满缓冲区:P(empty)
WaitForSingleObject(Empty, INFINITE);//一直等待
//进入缓冲区P(mutex)
EnterCriticalSection(&CR);
//取出数据
int r = Buffer[Buffer.size()-];
Buffer.pop_back();
cout << " Consumer consumes an element : " << r <<endl;
//退出缓冲区V(mutex)
LeaveCriticalSection(&CR);
//增加空缓冲区V(full)
ReleaseSemaphore(Full, , NULL);
//睡一会儿
Sleep();
}
} int main()
{
cout << "Input the number of BufferSize : "; cin >> BufferSize;
//创建信号量
Empty = CreateSemaphore(NULL, , BufferSize, NULL);
Full = CreateSemaphore(NULL, BufferSize, BufferSize,NULL); //初始化临界区
InitializeCriticalSection(&CR); int pNum, cNum;
cout << "Input the number of Producer(Max:10) : "; cin >> pNum;
cout << "Input the number of Consumer(Max:10) : "; cin >> cNum; //创建线程
int i;
HANDLE handle[];
for(i=; i<pNum; i++)
{
handle[i] = CreateThread(, , &Producer, , , );
}
for(i=pNum; i<pNum+cNum; i++)
{
handle[i] = CreateThread(, , &Consumer, , , );
} //回收线程
WaitForMultipleObjects(pNum+cNum, handle, true, INFINITE); //释放线程
for(i=; i<pNum+cNum; i++)
{
CloseHandle(handle[]);
} //释放缓冲区
DeleteCriticalSection(&CR);
return ;
}
结果:


2. 匿名管道(本地父进程与子进程通信)
原理:

源码:
/*
*匿名管道:父子进程通信
*date : 2018/12/3
*author : yocichen
*status : Done
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> int main()
{
//pipe1 p to s, pipe2 s to p
int fd_1[], fd_2[]; if(pipe(fd_1)< || pipe(fd_2)<)//fail to create pipe
{
printf("Fail to create the pipe.\n");
return -;
} char buf[];//
const char *temp; //child
int fork_result = fork();
if(fork_result == )
{
close(fd_1[]);//close read port
close(fd_2[]);//close write port //read message
read(fd_1[], buf, sizeof(buf));//read message from father port
printf("\nChild : receive a message from pipe1: %s\n", buf); //write message
temp = "Hi, my parent, I love you too.";
write(fd_2[], temp, strlen(temp));//child write message to pipe2
} else
{
close(fd_2[]);
close(fd_1[]); //write message
temp = "My child, I love you.";
write(fd_1[], temp, strlen(temp));//parent write message to pipe1 //read message
read(fd_2[], buf, sizeof(buf));//read message from pipe2
printf("\nParent : receive a message from pipe2: %s\n", buf);
}
return ;
}
(注意:该匿名管道程序为Linux系统开发,注意运行环境,windows下使用CodeBlocks可以运行)

3.命名管道
原理:

源码:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h> int main()
{
//创建命名管道
HANDLE namedPipe = CreateNamedPipeA("\\\\.\\pipe\\testName", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, , , , , NULL); //校验状态
if(namedPipe == INVALID_HANDLE_VALUE)
{
printf("Server: Fail to create named pipe.\n");
}
else
{
printf("Server: Succeed to create pipe.\n");
} OVERLAPPED op;
ZeroMemory(&op, sizeof(OVERLAPPED)); //创建事件对象
op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //等待连接
bool b = ConnectNamedPipe(namedPipe, &op);
printf("Server: Listen...\n"); int status = WaitForSingleObject(op.hEvent, INFINITE);
//连接成功
if(status == )
{
printf("Server: Succeed to connect.\n");
}
else
{
printf("Server: Fail to connect.\n");
} //通信
char buf[] = "来玩个猜数游戏吧!\n";
DWORD wp;
WriteFile(namedPipe, buf, strlen(buf), &wp, NULL); int ans = rand()%+;
while(status == )
{
ZeroMemory(buf, );
ReadFile(namedPipe, buf, , &wp, NULL);
printf("收到:%s\n", buf); if(int(buf[] - '') < ans)
{
WriteFile(namedPipe, "小了,再猜一次!\n", strlen("小了,再猜一次!\n"), &wp, NULL);
}
else if((buf[]-'') > ans)
{
WriteFile(namedPipe, "大了,再猜一次!\n", strlen("大了,再猜一次!\n"), &wp, NULL);
}
else
{
WriteFile(namedPipe, "猜对了!\n", strlen("小了,再猜一次!\n"), &wp, NULL);
break;
} if(buf[] == '')
{
printf("客户已退出!\n");
break;
}
} //通信结束
DisconnectNamedPipe(namedPipe);
return ;
}
Server
#include <windows.h>
#include <stdio.h>
#include <stdlib.h> int main()
{
//检查管道是否存在
bool b = WaitNamedPipeA("\\\\.\\pipe\\testName", ); //打开管道
HANDLE hFile = CreateFileA("\\\\.\\pipe\\testName", GENERIC_READ | GENERIC_WRITE, , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //是否连接成功
if(b == || hFile == INVALID_HANDLE_VALUE)
{
printf("Client: fail to connect.\n");
return ;
}
else
{
printf("Client: Succeed to connect.\n");
} //通信
char buf[];
ZeroMemory(buf, );
DWORD rp;
ReadFile(hFile, buf, , &rp, NULL);//读取
printf(buf); while(true)
{
printf("输入数字:");
scanf("%s", buf);
WriteFile(hFile, buf, strlen(buf), &rp, NULL); while(ReadFile(hFile, buf, , &rp, NULL) == true)
{
printf("Server: ");
printf(buf);
break;
}
} CloseHandle(hFile);
return ;
}
Client


4.Socket网络进程通信
原理:

源码:
/*注意头文件顺序*/
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib") //引入动态链接库 int main()
{
WORD ws_version = MAKEWORD(, ); //指定Winsock version
WSADATA wsaData; //WSA 函数的参数 /*初始化winsock*/
WSAStartup(ws_version, &wsaData); /*socket*/
SOCKET s_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN addr_server;
addr_server.sin_family = AF_INET; //协议
addr_server.sin_port = htons(); //端口
addr_server.sin_addr.s_addr = htonl(INADDR_ANY); //IP:任意IP /*bind*/
int bind_status;
bind_status = bind(s_server, (SOCKADDR*)&addr_server, sizeof(SOCKADDR));
if(bind_status == SOCKET_ERROR)
{
printf("bind error : fail to bind! \n");
}
else
{
printf("bind successfully!\n");
} /*listen*/
listen(s_server, );//max=5
printf("listening ... \n"); SOCKADDR_IN addr_client; //存储client地址信息
int len = sizeof(SOCKADDR);
int count = ; //统计客户数目
SOCKET s_client; //连接的socket char buf[];
while(true)
{
printf("等待客户端连接...\n");
/*accept*/
s_client = accept(s_server, (SOCKADDR*)&addr_client, &len);
if(s_client == INVALID_SOCKET)
{
printf("Accept error : fail to accept client! ");
}
else//连接成功
{
count++;
printf("\nAccept successfully!\n"); printf("---------------------------------------------\n");
printf(" 编号:%d \n", count);
printf(" Port:%d\n", ntohs(addr_client.sin_port));
printf(" IP:%s\n", inet_ntoa(addr_client.sin_addr));//inet_ntoa(SOCKADDR.in_addr)网络地址转换为IP int recv_status = recv(s_client, buf, , );
if(recv_status > )
{
printf("收到:");
buf[recv_status] = 0x00;//截断
printf(buf);
printf("\n---------------------------------------------\n");
}
const char *sendData = "你好!客户端!我是服务器";
send(s_client, sendData, strlen(sendData), );
closesocket(s_client);
}
} closesocket(s_server); //关闭socket
WSACleanup(); return ;
}
Server
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib") //引入动态链接库
#define SERVER_IP "192.168.31.102" //客户端IP
using namespace std; int main()
{
WORD ws_version = MAKEWORD(, ); //指定Winsock version
WSADATA wsaData; //WSA 函数的参数 /*初始化winsock*/
WSAStartup(ws_version, &wsaData); while(true)
{
/*socket*/
SOCKET s_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN addr_server;
addr_server.sin_family = AF_INET; //协议
addr_server.sin_port = htons(); //端口
addr_server.sin_addr.s_addr = inet_addr(SERVER_IP); char buf[];
int send_status, recv_status; /*Connect*/
int cnct_status = connect(s_client, (SOCKADDR*)&addr_server, sizeof(SOCKADDR));
if(cnct_status == )//连接成功
{
printf("\nConnecting... done\n"); //向服务端发送消息
printf("输入发送信息:");
scanf("%s", buf);
send_status = send(s_client, buf, , );
if(send_status == SOCKET_ERROR)//发送失败
{
printf("send error!\n");
}
else
{
printf("发送:%s\n", buf);
//接受服务端消息
recv_status = recv(s_client, buf, , );
buf[recv_status] = 0x00;//截断
printf("收到:%s\n", buf);
}
}
else
{
printf("Test:fail to connect server! \n");
}
closesocket(s_client);
} WSACleanup(); return ;
}
Client


操作系统-进程通信(信号量、匿名管道、命名管道、Socket)的更多相关文章
- 邮槽 匿名管道 命名管道 剪贴板 进程通讯 转自http://www.cnblogs.com/kzloser/archive/2012/11/04/2753367.html#
邮槽 通信流程: 服务器 客户端 注意: 邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输 邮槽可以实现一对多的单向通信,我们可以利用这个特点编写一个网络会议通知系统,而且实现这一的系 ...
- Linux进程通信之匿名管道
进程间的通信方式 进程间的通信方式包括,管道.共享内存.信号.信号量.消息队列.套接字. 进程间通信的目的 进程间通信的主要目的是:数据传输.数据共享.事件通知.资源共享.进程控制等. 进程间通信之管 ...
- C#命名管道通信
C#命名管道通信 最近项目中要用c#进程间通信,以前常见的方法包括RMI.发消息等.但在Windows下面发消息需要有窗口,我们的程序是一个后台运行程序,发消息不试用.RMI又用的太多了,准备用管道通 ...
- c# c++通信--命名管道通信
进程间通信有很多种,windows上面比较简单的有管道通信(匿名管道及命名管道) 最近做个本机c#界面与c++服务进行通信的一个需求.简单用命名管道通信.msdn都直接有demo,详见下方参考. c+ ...
- [转]WINDOW进程通信的几种方式
windows进程通信的几种方式 1 文件映射 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/O操作,只需简单的指针 ...
- 【windows 操作系统】进程间通信(IPC)简述|无名管道和命名管道 消息队列、信号量、共享存储、Socket、Streams等
一.进程间通信简述 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进 ...
- C++和C#进程之间通过命名管道通信(上)
C++和C#进程之间通过命名管道通信(上) "命名管道"是一种简单的进程间通信(IPC)机制.命名管道可在同一台计算机的不同进程之间,或在跨越一个网络的不同计算机的不同进程之间,支 ...
- 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)
RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三 多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...
- Linux下进程通信之管道
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把 ...
随机推荐
- vsCode 设置vue 保存自动格式化代码
setting { // vscode默认启用了根据文件类型自动设置tabsize的选项 "editor.detectIndentation": false, // 重新设定tab ...
- Ajax 提交 数据含特殊字符 出现500错误
Ajax 请求API接口 传输过去的数据 含有特殊字符,Ajax请求失败出现500错误. 假设你要post过去的数据为 :data ==>> {a:'!@!@!@!@#$#{}|> ...
- 开发中常用js记录(三)
(1)Jquery 判断一个元素下是否有指定的class$('div').is('.classname')$('div').hasClass('redColor') (2)获得窗口长宽等$(windo ...
- list源码4(参考STL源码--侯捷):transfer、splice、merge、reverse、sort
list源码1(参考STL源码--侯捷):list节点.迭代器.数据结构 list源码2(参考STL源码--侯捷):constructor.push_back.insert list源码3(参考STL ...
- ASP.NET Core 如何在运行Docker容器时指定容器外部端口(docker compose)
前面我写了一系列关于持续集成的文章,最终构建出来的镜像运行之后,应该会发现每次构建运行之后端口都变了,这对于我们来说是十分不方便的,所以我们可以通过修改docker compose的配置文件来完成我们 ...
- 全网最详细的最新稳定OSSEC搭建部署(ossec-server(CentOS7.X)和ossec-agent(CentOS7.X))(图文详解)
不多说,直接上干货! 前言 写在前面的话,网上能够找到一些关于ossec方面的资料,虽然很少,但是总比没有强,不过在实际的使用过程中还是会碰到许多稀奇古怪的问题.整理整理我的使用过程,就当做一篇笔记吧 ...
- 全网最详细的Centos7系统里安装Openresty(图文详解)
不多说,直接上干货! 介绍: Nginx 采用一个 master 进程管理多个 worker 进程(master-worker)模式,基本的事件处理都在 woker 中,master 负责一些全局初始 ...
- DWR第四篇之对象传参
1. 本示例在第一篇架构基础上添加代码 2. 首先,在dwr.xml文件里添加对象转换器 3. 编写Person实体类 package com.skyer.vo; import java.util.A ...
- 【杂谈】没有公网IP的电脑如何与外部通信
前言 前几天突然想到的问题,自己先猜测推理了一番,最后在谢希仁版<计算机网络>找到了权威的解答.这里记录一下自己的思考过程. 网站是如何找到我们的? 我们知道,互联网中的两台电脑要进行通信 ...
- Python获得百度统计API的数据并发送邮件
Python获得百度统计API的数据并发送邮件 小工具 本来这么晚是不准备写博客的,当是想到了那个狗子绝对会在开学的时候跟我逼逼这个事情,所以,还是老老实实地写一下吧. Baidu统计API的使 ...