邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠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核心编程》---邮槽通信相关推荐

  1. C++Windows核心编程读书笔记(转)

    http://www.makaidong.com/(马开东博客) 这篇笔记是我在读<windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的 ...

  2. [C++]《Windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  3. 内存映射文件——Windows核心编程学习手札之十七

    内存映射文件 --Windows核心编程学习手札之十七 与虚拟内存一样,内存映射文件保留地址空间,并将物理存储器提交给该区域,差别在于所提交的物理存储器是磁盘上有文件存在的空间,而非系统的页文件,一旦 ...

  4. 用户方式中线程的同步——Windows核心编程学习手札之八

    用户方式中线程的同步 --Windows核心编程学习手札之八 系统中所有线程都必须拥有对各种系统资源的访问权,这些资源包括内存堆栈.串口.文件.窗口和许多其他资源.如果一个线程需要独占对资源的访问权, ...

  5. 线程与内核对象的同步——Windows核心编程学习手札之九

    线程与内核对象的同步 --Windows核心编程学习手札之九 用户方式下的线程同步机制具有速度快的特点,但有其局限性,对于许多应用程序来说,并不合适.例如,互锁函数家族只能在单值上运行,根本无法使线程 ...

  6. Unicode——Windows核心编程学习手札之二

    Unicode --Windows核心编程学习手札之二 处理软件本地化的核心在于处理不同的字符集.文本串一直作为一系列单字节字符进行编码,并在结尾处放上一个零,当调用strlen函数时,获取以/0结尾 ...

  7. 我对windows核心编程的理解之一

    看了几天windows核心编程VC++,前几天对进程,作业,线程的关系很迷惑,还有就是内核对象的应用也很迷茫.昨天自己拿着书,又翻过去看看.突然有一点心得,初步对windows下的三种工作单位有了新的 ...

  8. 《Windows核心编程系列》九谈谈同步设备IO与异步设备IO之同步设备IO

    <Windows核心编程系列>九谈谈同步设备IO与异步设备IO之同步设备IO 同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请 ...

  9. 《windows核心编程系列》二谈谈ANSI和Unicode字符集

    第二章:字符和字符串处理 使用vc编程时项目-->属性-->常规栏下我们可以设置项目字符集合,它可以是ANSI(多字节)字符集,也可以是unicode字符集.一般情况下说Unicode都是 ...

最新文章

  1. 关于modbus温湿度传感器,IIC热成像仪相关知识点总结
  2. strcpy和memcpy的区别 | strcpy和strncpy的区别
  3. Py之fvcore:fvcore库的简介、安装、使用方法之详细攻略
  4. python将照片转文字_Python将图片转化成文字
  5. python sqllite远程_Python实现Sqlite将字段当做索引进行查询的方法
  6. HTML/CSS常用标签属性及样式
  7. python获取程序文件中的全局变量和局部变量的函数
  8. c语言学习-自定义函数并调用求1-100的累计和
  9. 53 - leetcode 1. 两数之和 数据结构map类
  10. vue将经纬度转换成地理名称_新武汉北,红安有了一个新的地理名称,恒大项目将对标上海迪士尼...
  11. java cas原理_Java中的锁[原理、锁优化、CAS、AQS]
  12. 3月28日 simulink学习(一)
  13. (1) python 将numpy数组导出excel
  14. E: 错误,pkgProblemResolver::Resolve 发生故障,这可能是有软件包被要求保持现状的缘故
  15. 梁肇新-豪杰超级解霸
  16. 一位程序员社畜的2021闲读书单!
  17. 图的两种遍历:深度优先遍历+广度优先遍历
  18. 做PPT只会用黑体和宋体?这些可商用字体瞬间提升你的PPT档次
  19. access select max_超级玛丽2号Max:挑选重疾险需要避开这3大误区!
  20. 初学者学Java常遇到的问题,我都给你回答了!

热门文章

  1. dispatch作用 react_「React系列」手把手带你撸后台系统(Redux与路由鉴权)
  2. 个人计算机技术分享,一个计算机类本科毕业设计分享
  3. shadowplay要下载java_Java并发程序设计(二)Java并行程序基础
  4. 插件编写傻瓜教程VC6.0
  5. 自定义SpringBoot项目的Maven原型
  6. 看我如何跨虚拟机实现Row Hammer攻击和权限提升
  7. 错误:无法访问android.app.Activity 找不到android.app.Activity的类文件
  8. python 没有了matlab的fscanf功能,我该怎么办
  9. (转)浅析当今视频文件的格式
  10. 三个免费图片网站:特别适合场景图