Loading AI tools
来自维基百科,自由的百科全书
郵槽 (MailSlot)是Windows作業系統提供的一種單向進程間通信機制,可用於單機或者網絡上的多機分佈式環境。[1]
此條目需要補充更多來源。 (2017年9月3日) |
對於相對簡短的低頻率信息發送,使用郵槽通常比命名管道或Unix域套接字更簡單。如低頻率的狀態改變消息、作為對等點發現協議(peer-discovery protocol)的一部分。 郵槽機制允許短報文廣播給域上的計算機中所有監聽的進程。
郵槽是一種伺服器-客戶接口。伺服器創建郵槽,客戶可以向命名的郵槽寫入內容。只有伺服器可以讀取郵槽,因此郵槽是一種單向進程間通信機制。郵槽不提供報文已收到的確認,因此是不可靠通信。
郵槽基於RPC協議,可以在同一個網絡域上跨計算機使用。
Windows信使服務是郵槽的最知名的應用。信使服務是一個郵槽伺服器,等待報文到達後,就彈窗顯示在屏幕上。
郵槽的應用舉例:
NET SEND
協議郵槽的名字,從形式上看類似於文件名。格式為\\ComputerName\mailslot\[path]name
本地郵槽名字中的ComputerName使用 .
來代替,即\\.\MailSlot\路径\文件名
。如果向當前發送計算機所在工作組或域群發,可以使用 *
作為ComputerName。如果向指定工作組或域群發,應使用工作組或域名作為ComputerName
本機的Windows的信使服務使用的郵槽名字是\\.\MailSlot\ messngr
郵槽報文內容包含:接收日期、發送人、接收人、具體內容。發送人、接收人、具體內容三項內容之間使用字節值0
間隔。
使用CreateMailslot
類似於寫入普通文件,使用CreateFile
打開郵槽,使用WriteFile
將內容寫入。
也可以使用NetMessageBufferSend
直接發送。
使用GetMailSlotInfo
來判斷郵槽內是否有內容。發現有內容的時候,可以使用ReadFile
讀取。如果ReadFile
在使用MAILSLOT_WAIT_FOREVER標誌的郵槽上等待消息到來,這時郵槽突然中止運行,那麼這個應用會被永遠「掛起」直至重啟Windows系統。為此,讀郵槽的進程可以使用一個單獨線程執行讀掛起操作;主線程要結束進程時給一個全局標誌位置位,並給郵槽寫入一條消息以喚醒讀郵槽線程。
SetMailslotInfo
設置讀取郵槽的超時值
//邮槽服务器,负责创建邮槽,读取邮槽
#include <windows.h>
#include <stdio.h>
int main()
{
HANDLE Mailslot;
char buffer[256];
DWORD NumberOfBytesRead;
//Create the mailslot
Mailslot = CreateMailslot("////.//Mailslot//Myslot", //指定邮槽的名字
0, //可写入邮槽的消息的最大字节长度;为0表示接收任意长度消息
MAILSLOT_WAIT_FOREVER, //等待或不等待,单位毫秒,MAILSLOT_WAIT_FOREVER无限期等待,0立即返回
NULL); //访问控制权限,一般为NULL
if (INVALID_HANDLE_VALUE == Mailslot)
{
printf("Failed to create a mailslot %d/n", GetLastError());
return -1;
}
//Read data from the mailslot forever!
while (0 != ReadFile(Mailslot, buffer, 256, &NumberOfBytesRead, NULL))
{
printf("%.*s/n",NumberOfBytesRead,buffer);
}
CloseHandle(Mailslot);
return 0;
}
//邮槽客户端,用于发送数据到邮槽服务器
#include <windows.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
HANDLE Mailslot;
DWORD BytesWritten;
CHAR ServerName[256];
//从命令行接受要发送数据到的服务器名
if (argc < 2)
{
printf("Usage: client <server name>/n");
return -1;
}
sprintf(ServerName, "////%s//Mailslot//Myslot",argv[1]);
Mailslot = CreateFile(ServerName, //邮槽名字
GENERIC_WRITE, //必须为GENERIC_WRITE,因为客户端只能向邮槽写入数据
FILE_SHARE_READ, /必须为FILE_SHARE_READ,因为邮槽服务器需要做打开和读操作
NULL,
OPEN_EXISTING, //邮槽在本地且还没有创建邮槽则当前调用失败;邮槽在远程,该参数无意义
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == Mailslot)
{
printf("WriteFile failed with error %d/n",GetLastError());
return -1;
}
if(0 == WriteFile(Mailslot, "This is a test", 14, &BytesWritten,NULL))
{
printf("WriteFile failed with error %d/n", GetLastError());
return -1;
}
printf("Wrote %d byteds/n", BytesWritten);
CloseHandle(Mailslot);
return 0;
}