《Windows核心编程》---邮槽通信
邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠UDP数据传输协议。使用邮槽通信的进程分为客户端和服务端,邮槽由服务端创建,创建后,客户端可以通过邮槽名打开邮槽,在获得邮槽句柄后可以向邮槽写入消息。邮槽通信是单向的,只有服务端能从邮槽中读取消息,而客户端只能写入消息。消息是先进先出的。
通过邮槽通信的数据可以是任意格式的,但为了保证邮槽在各种Windows平台下都能够正常工作,邮槽通信一条消息的长度不能大于424字节。邮槽除了在本机上进行进程间通信外,还可以在主机之间进行通信。
实际上一个邮槽是驻留在内存中的一个Windows临时虚拟文件,利用Windows标准文件函数可以对邮槽写入或读取消息,但它不同于磁盘文件的地方是:当邮槽句柄被关闭后,邮槽中的消息将被全部删除。
因此,邮槽工作方式有三大特定:1)单向通信;2)广播消息;3)数据报传输。
1)邮槽的命名:
本机上邮槽命名格式://./mailslot/[path/]name;
例如://./mailslot/win/asce_comment;
不同主机间命名格式://DomainName/mailslot/[path/]name;
//ComputerName/mailslot/[path/]name;
也可以使用通配符,以进行广播://*/mailslot/[path/]name;
格式的说明:前两个反斜杠之后的字符表示服务器所在机器的名称,圆点表示是本地主机;“mailslot”是硬编码的,这几个字符不能改变,但大小写无所谓。“[path/]name”当然就是邮槽名字了。
2)关键的API
CreateMailslot,创建一个邮槽对象:
HANDLE WINAPI CreateMailslot(
__in LPCTSTR lpName, //邮槽名
__in DWORD nMaxMessageSize, //单一消息最大长度,为了可以发送任意大小的消息,
//一般将该参数设置为0
__in DWORD lReadTimeout, //读超时的时间:0(如果没有消息时立即返回);
//MAILSLOT_WAIT_FOREVER(直到读到消息才返回)
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes //安全属性
);
例子如下:
#include <windows.h>
#include <stdio.h>
HANDLE hSlot;
LPTSTR Slot = TEXT(".//mailslot//sample_mailslot");
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
hSlot = CreateMailslot(lpszSlotName,
0, // no maximum message size
MAILSLOT_WAIT_FOREVER, // no time-out for operations
(LPSECURITY_ATTRIBUTES) NULL); // default security
if (hSlot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot failed with %d/n", GetLastError());
return FALSE;
}
else printf("Mailslot created successfully./n");
return TRUE;
}
void main()
{
MakeSlot(Slot);
}
GetMailslotInfo,获取指定邮槽的相关信息:
BOOL WINAPI GetMailslotInfo(
__in HANDLE hMailslot, //邮槽的句柄
__out_opt LPDWORD lpMaxMessageSize, //返回消息的最大长度
__out_opt LPDWORD lpNextSize, //返回下一条消息的长度
__out_opt LPDWORD lpMessageCount, //返回消息的数量
__out_opt LPDWORD lpReadTimeout //返回读超时时间
);
例子如下:(这个例子同时是一个完整的邮槽服务端)
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
HANDLE hSlot;
LPTSTR SlotName = TEXT(".//mailslot//sample_mailslot");
BOOL ReadSlot()
{
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPTSTR lpszBuffer;
TCHAR achID[80];
DWORD cAllMessages;
HANDLE hEvent;
OVERLAPPED ov;
cbMessage = cMessage = cbRead = 0;
hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
if( NULL == hEvent )
return FALSE;
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;
fResult = GetMailslotInfo( hSlot, // mailslot handle
(LPDWORD) NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD) NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed with %d./n", GetLastError());
return FALSE;
}
if (cbMessage == MAILSLOT_NO_MESSAGE)
{
printf("Waiting for a message.../n");
return TRUE;
}
cAllMessages = cMessage;
while (cMessage != 0) // retrieve all messages
{
// Create a message-number string.
StringCchPrintf((LPTSTR) achID,
80,
TEXT("/nMessage #%d of %d/n"),
cAllMessages - cMessage + 1,
cAllMessages);
// Allocate memory for the message.
lpszBuffer = (LPTSTR) GlobalAlloc(GPTR,
lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage);
if( NULL == lpszBuffer )
return FALSE;
lpszBuffer[0] = '/0';
fResult = ReadFile(hSlot,
lpszBuffer,
cbMessage,
&cbRead,
&ov);
if (!fResult)
{
printf("ReadFile failed with %d./n", GetLastError());
GlobalFree((HGLOBAL) lpszBuffer);
return FALSE;
}
// Concatenate the message and the message-number string.
StringCbCat(lpszBuffer,
lstrlen((LPTSTR) achID)*sizeof(TCHAR)+cbMessage,
(LPTSTR) achID);
// Display the message.
_tprintf(TEXT("Contents of the mailslot: %s/n"), lpszBuffer);
GlobalFree((HGLOBAL) lpszBuffer);
fResult = GetMailslotInfo(hSlot, // mailslot handle
(LPDWORD) NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD) NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed (%d)/n", GetLastError());
return FALSE;
}
}
CloseHandle(hEvent);
return TRUE;
}
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
hSlot = CreateMailslot(lpszSlotName,
0, // no maximum message size
MAILSLOT_WAIT_FOREVER, // no time-out for operations
(LPSECURITY_ATTRIBUTES) NULL); // default security
if (hSlot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot failed with %d/n", GetLastError());
return FALSE;
}
return TRUE;
}
void main()
{
MakeSlot(SlotName);
while(TRUE)
{
ReadSlot();
Sleep(3000);
}
}
SetMailslotInfo,修改已创建邮槽读操作的超时时间:
BOOL WINAPI SetMailslotInfo(
__in HANDLE hMailslot, //邮槽句柄
__in DWORD lReadTimeout //新的读超时时间
);
邮槽的客户端代码如下:
#include <windows.h>
#include <stdio.h>
LPTSTR SlotName = TEXT(".//mailslot//sample_mailslot");
BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage)
{
BOOL fResult;
DWORD cbWritten;
fResult = WriteFile(hSlot,
lpszMessage,
(DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR),
&cbWritten,
(LPOVERLAPPED) NULL);
if (!fResult)
{
printf("WriteFile failed with %d./n", GetLastError());
return FALSE;
}
printf("Slot written to successfully./n");
return TRUE;
}
int main()
{
HANDLE hFile;
hFile = CreateFile(SlotName,
GENERIC_WRITE,
FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with %d./n", GetLastError());
return FALSE;
}
WriteSlot(hFile, TEXT("Message one for mailslot."));
WriteSlot(hFile, TEXT("Message two for mailslot."));
Sleep(5000);
WriteSlot(hFile, TEXT("Message three for mailslot."));
CloseHandle(hFile);
return TRUE;
}
由于邮槽是基于广播通信的,所以邮槽可以实现一对多的单向通信,例如,我们可以利用邮槽编写一个网络会议的通知系统。在每个被通知人电脑上安装服务端,通知人电脑上安装客户端即可。
《Windows核心编程》---邮槽通信相关推荐
- C++Windows核心编程读书笔记(转)
http://www.makaidong.com/(马开东博客) 这篇笔记是我在读<windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的 ...
- [C++]《Windows核心编程》读书笔记
这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...
- 内存映射文件——Windows核心编程学习手札之十七
内存映射文件 --Windows核心编程学习手札之十七 与虚拟内存一样,内存映射文件保留地址空间,并将物理存储器提交给该区域,差别在于所提交的物理存储器是磁盘上有文件存在的空间,而非系统的页文件,一旦 ...
- 用户方式中线程的同步——Windows核心编程学习手札之八
用户方式中线程的同步 --Windows核心编程学习手札之八 系统中所有线程都必须拥有对各种系统资源的访问权,这些资源包括内存堆栈.串口.文件.窗口和许多其他资源.如果一个线程需要独占对资源的访问权, ...
- 线程与内核对象的同步——Windows核心编程学习手札之九
线程与内核对象的同步 --Windows核心编程学习手札之九 用户方式下的线程同步机制具有速度快的特点,但有其局限性,对于许多应用程序来说,并不合适.例如,互锁函数家族只能在单值上运行,根本无法使线程 ...
- Unicode——Windows核心编程学习手札之二
Unicode --Windows核心编程学习手札之二 处理软件本地化的核心在于处理不同的字符集.文本串一直作为一系列单字节字符进行编码,并在结尾处放上一个零,当调用strlen函数时,获取以/0结尾 ...
- 我对windows核心编程的理解之一
看了几天windows核心编程VC++,前几天对进程,作业,线程的关系很迷惑,还有就是内核对象的应用也很迷茫.昨天自己拿着书,又翻过去看看.突然有一点心得,初步对windows下的三种工作单位有了新的 ...
- 《Windows核心编程系列》九谈谈同步设备IO与异步设备IO之同步设备IO
<Windows核心编程系列>九谈谈同步设备IO与异步设备IO之同步设备IO 同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请 ...
- 《windows核心编程系列》二谈谈ANSI和Unicode字符集
第二章:字符和字符串处理 使用vc编程时项目-->属性-->常规栏下我们可以设置项目字符集合,它可以是ANSI(多字节)字符集,也可以是unicode字符集.一般情况下说Unicode都是 ...
最新文章
- 关于modbus温湿度传感器,IIC热成像仪相关知识点总结
- strcpy和memcpy的区别 | strcpy和strncpy的区别
- Py之fvcore:fvcore库的简介、安装、使用方法之详细攻略
- python将照片转文字_Python将图片转化成文字
- python sqllite远程_Python实现Sqlite将字段当做索引进行查询的方法
- HTML/CSS常用标签属性及样式
- python获取程序文件中的全局变量和局部变量的函数
- c语言学习-自定义函数并调用求1-100的累计和
- 53 - leetcode 1. 两数之和 数据结构map类
- vue将经纬度转换成地理名称_新武汉北,红安有了一个新的地理名称,恒大项目将对标上海迪士尼...
- java cas原理_Java中的锁[原理、锁优化、CAS、AQS]
- 3月28日 simulink学习(一)
- (1) python 将numpy数组导出excel
- E: 错误,pkgProblemResolver::Resolve 发生故障,这可能是有软件包被要求保持现状的缘故
- 梁肇新-豪杰超级解霸
- 一位程序员社畜的2021闲读书单!
- 图的两种遍历:深度优先遍历+广度优先遍历
- 做PPT只会用黑体和宋体?这些可商用字体瞬间提升你的PPT档次
- access select max_超级玛丽2号Max:挑选重疾险需要避开这3大误区!
- 初学者学Java常遇到的问题,我都给你回答了!
热门文章
- dispatch作用 react_「React系列」手把手带你撸后台系统(Redux与路由鉴权)
- 个人计算机技术分享,一个计算机类本科毕业设计分享
- shadowplay要下载java_Java并发程序设计(二)Java并行程序基础
- 插件编写傻瓜教程VC6.0
- 自定义SpringBoot项目的Maven原型
- 看我如何跨虚拟机实现Row Hammer攻击和权限提升
- 错误:无法访问android.app.Activity 找不到android.app.Activity的类文件
- python 没有了matlab的fscanf功能,我该怎么办
- (转)浅析当今视频文件的格式
- 三个免费图片网站:特别适合场景图