進(jìn)程通信——郵槽和命名管道
今天記錄下自己學(xué)的郵槽和命名管道,學(xué)習(xí)過程中遇到點(diǎn)問題也拿出來分享下。哈 開整先說一下大體的概念?yuàn)W。
郵槽定義
郵槽(Mailslot)也稱為郵件槽,是Windows 提供的進(jìn)程間通信的手段,
其提供的是基于不可靠的,郵件槽只支持單向數(shù)據(jù)傳輸,也就是服務(wù)器只能接收數(shù)據(jù),而客戶端只能發(fā)送數(shù)據(jù),
何為服務(wù)端?創(chuàng)建郵槽的那一端就是服務(wù)端。
還有需要提及的一點(diǎn)是,客戶端在使用郵槽發(fā)送數(shù)據(jù)的時(shí)候只有當(dāng)數(shù)據(jù)的長度 < 425 字節(jié)時(shí),
才可以被廣播給多個(gè)服務(wù)器,如果消息的長度 > 425 字節(jié)的話,那么在這種情形下,郵槽是不支持廣播通信的。
這是我看到的郵槽的簡要說明吧。
先說下郵槽的使用過程吧。然后再分析函數(shù),在貼代碼。非常簡單哦
服務(wù)端: 客戶端:
首先創(chuàng)建郵槽CreateMailslot 打開油槽CreateFile
讀取數(shù)據(jù) ReadFile 寫入數(shù)據(jù)WriteFile
完事了,只有這四個(gè)函數(shù)。也很容易理解。 客戶端寫入數(shù)據(jù) 服務(wù)端讀取數(shù)據(jù)。
CreateMailslot(_T("\\\\.\\mailslot\\chenxiao"),0, MAILSLOT_WAIT_FOREVER,NULL);
第一個(gè)參數(shù)是個(gè)固定格式\\.\\mailslot\\name 點(diǎn)代表本機(jī)。mailslot是硬編碼 不能變,name可以自己起個(gè)郵槽的名字。‘\’放入字符串中要用轉(zhuǎn)義字符\
所以就寫成了"\\\\.\\mailslot\\chenxiao"
第二個(gè)參數(shù)To specify that the message can be of any size, set this value to zero. 設(shè)置成0
第三個(gè)參數(shù)為了下面的讀取操作應(yīng)該等待的時(shí)間 MAILSLOT_WAIT_FOREVER 傳這個(gè)代表參數(shù)代表永久等待。
最后一個(gè)參數(shù)安全屬性 嘎嘎 null
ReadFile(hMailSlot,pData,sizeof(TCHAR)*80,&dByteRead,NULL);
這幾個(gè)參數(shù)很簡單了。第一個(gè)參數(shù)就是創(chuàng)建郵槽返回來的句柄 第二個(gè)參數(shù)一個(gè)[out]buffer用來接收從郵槽中讀出來的東東。第三個(gè)參數(shù)就是讀取多少個(gè)字節(jié)。
第四個(gè)參數(shù)基本沒用,是一個(gè)[out]的LPDWord 很蛋疼只能DWORD dByteRead; 然后傳個(gè)他的地址。
因?yàn)閙sdn上說了If lpOverlapped is NULL, lpNumberOfBytesRead cannot be NULL;
lpoverlapped就是我們的最后一個(gè)參數(shù),這個(gè)參數(shù)可以設(shè)置同步和異步,如果文件打開模式是FILE_FLAG_OVERLAPPED這個(gè)的話,我們這個(gè)就不可以是NULL
這個(gè)同步異步問題我在下面的命名管道中在說。這里就先過去。這個(gè)參數(shù)設(shè)成NULL。
客戶端函數(shù)
CreateFile(_T("\\\\.\\mailslot\\chenxiao"),GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
這幾個(gè)參數(shù)也很容易理解了。第一個(gè)參數(shù)要和創(chuàng)建郵槽的時(shí)候的參數(shù)一樣。如果要遠(yuǎn)程通信的話可以把‘.’設(shè)置成服務(wù)器 主機(jī)名 或者在一個(gè)區(qū)域內(nèi)廣播‘*’
但是我用兩個(gè)機(jī)器實(shí)驗(yàn)了,沒有成功,目前我只能用郵槽在本地一個(gè)機(jī)器上通信。。。尷尬。。有知道怎么在兩個(gè)機(jī)器上通信的,要給我留言教教我哦。
后幾個(gè)參數(shù)根據(jù)參數(shù)名大家就可以猜個(gè)差不多了,我就不說了。吼吼。
WriteFile(hMailSlot,str,sizeof(TCHAR)*80,&dByteWrite,NULL);這個(gè)函數(shù) 跟 readfile差不多 就是向郵槽中寫入數(shù)據(jù)用的。
第二個(gè)參數(shù)是要寫入的內(nèi)容,第三個(gè)是大小(以字節(jié)為單位).
好了這幾個(gè)函數(shù)都說完了。貼上小代碼,就清晰了。









































這就是運(yùn)行結(jié)果啦。這個(gè)東西沒啥大用。就是學(xué)習(xí)一下而已。以后萬一用到也能弄弄。
下面我說下命名管道。這個(gè)東西坑了我一下午。。。
郵槽建立的是無連接的通信。。那么命名管道 就是有鏈接的可靠的通信了。他跟郵槽挺相似的。但是比郵槽好很多。
同上面。我粘一些概念性的東西。
命名管道是通過網(wǎng)絡(luò)來完成進(jìn)程之間的通信的,命名管道依賴于底層網(wǎng)絡(luò)接口,
其中包括有 DNS 服務(wù),TCP/IP 協(xié)議等等機(jī)制,但是其屏蔽了底層的網(wǎng)絡(luò)協(xié)議細(xì)節(jié),
對(duì)于匿名管道而言,其只能實(shí)現(xiàn)在父進(jìn)程和子進(jìn)程之間進(jìn)行通信,而對(duì)于命名管道而言,
其不僅可以在本地機(jī)器上實(shí)現(xiàn)兩個(gè)進(jìn)程之間的通信,還可以跨越網(wǎng)絡(luò)實(shí)現(xiàn)兩個(gè)進(jìn)程之間的通信。
命名管道使用了 Windows 安全機(jī)制,因而命名管道的服務(wù)端可以控制哪些客戶有權(quán)與其建立連接,
而哪些客戶端是不能夠與這個(gè)命名管道建立連接的。
利用命名管道機(jī)制實(shí)現(xiàn)不同機(jī)器上的進(jìn)程之間相互進(jìn)行通信時(shí),
可以將命名管道作為一種網(wǎng)絡(luò)編程方案時(shí),也就是看做是 Socket 就可以了,
它實(shí)際上是建立了一個(gè)客戶機(jī)/服務(wù)器通信體系,并在其中可靠的傳輸數(shù)據(jù)。
命名管道的通信是以連接的方式來進(jìn)行的,
服務(wù)器創(chuàng)建一個(gè)命名管道對(duì)象,然后在此對(duì)象上等待連接請(qǐng)求,
一旦客戶連接過來,則兩者都可以通過命名管道讀或者寫數(shù)據(jù)。
命名管道提供了兩種通信模式:字節(jié)模式和消息模式。
在字節(jié)模式下,數(shù)據(jù)以一個(gè)連續(xù)的字節(jié)流的形式在客戶機(jī)和服務(wù)器之間流動(dòng),
而在消息模式下,客戶機(jī)和服務(wù)器則通過一系列的不連續(xù)的數(shù)據(jù)單位,進(jìn)行數(shù)據(jù)的收發(fā),
每次在管道上發(fā)出一個(gè)消息后,它必須作為一個(gè)完整的消息讀入。
我相信很多人看了幾句就跳到這里來了。。概念性的東西 確實(shí)太不好玩了。我也不愛看。。哈哈
介紹命名管道需要的函數(shù)。
服務(wù)器端
CreateNamedPipe 創(chuàng)建命名管道
ConnectNamedPip 連接
ReadFile 讀
WriteFile 寫
客戶端
WaitNamedPipe 查看命名管道
CreateFile 打開命名管道
WriteFile ReadFile 寫 讀
就這些東西,今天由于不仔細(xì)看msdn 寫程序?qū)懨闪恕!!5葧?huì)我在說啊。大家要注意哦。
CreateNamedPipe(_T("\\\\.\\pipe\\chenxiao"),PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,1,1024,1024,2000,NULL);
很多參數(shù)啊!不怕不怕 慢慢來
第一個(gè)我略過了哦。第二個(gè)大家在msdn上可以看到有
PIPE_ACCESS_DUPLEX 讀寫雙向
PIPE_ACCESS_INBOUND 數(shù)據(jù)只能從客戶端到服務(wù)端
PIPE_ACCESS_OUTBOUND 和上面那個(gè)相反
這個(gè)參數(shù)我們?cè)O(shè)置成 第一個(gè)。然而通過msdn大家可以看到這個(gè)參數(shù)可以附加 flag 我們就附加FILE_FLAG_OVERLAPPED 這個(gè)了
MSDN那一大堆英文我也瞅不太明白,大至意思就是這個(gè)呢 用了這個(gè)參數(shù) 程序操作讀,寫,連接等操作,可以立馬返回。比如說讀一個(gè)大文件吧
你把這個(gè)文件從頭讀到偉 需要很長時(shí)間。這樣的話你的readfile函數(shù)就不會(huì)反回 就會(huì)阻塞在那里一直讀。這樣很不好,所以有了這個(gè)參數(shù)。這個(gè)參數(shù)就是使你的讀 寫 等待函數(shù)立馬返回,這個(gè)就屬于程序的異步,這個(gè)讀函數(shù)和主程序一起執(zhí)行。
下一個(gè)參數(shù)就是以字節(jié)流還是消息方式發(fā)送文件 讀取文件。我們采用字節(jié)流方式PIPE_TYPE_BYTE。
下一個(gè)參數(shù)是最多可以創(chuàng)建幾個(gè)命名管道 比如我們?cè)O(shè)置成3,就是可以創(chuàng)建3個(gè)這樣的管道。我們這里設(shè)置成1,我們只用一個(gè)管道做演示就行。然后是分配的輸入 輸出 緩沖區(qū)大小 ,就類似創(chuàng)建線程時(shí)分配棧空間大小一樣。然后是一個(gè)超時(shí)時(shí)間設(shè)置 這個(gè)設(shè)置成0就可以。最后一個(gè)NULL安全屬性
ConnectNamedPipe服務(wù)端的連接管道函數(shù)這個(gè)函數(shù)兩個(gè)參數(shù)第一個(gè)參數(shù)句柄,第二個(gè)參數(shù)一個(gè)結(jié)構(gòu)體對(duì)象
這個(gè)結(jié)構(gòu)體呢 里面有一個(gè)事件句柄。剛才上邊由于設(shè)置了異步,所以你要有一個(gè)標(biāo)志著讀結(jié)束的標(biāo)志,這個(gè)標(biāo)志就用的這個(gè)事件。創(chuàng)建這個(gè)事件要設(shè)置成手動(dòng)的,初始為無信號(hào)。
這樣服務(wù)端的就寫完了。
然后再說一下客戶端的函數(shù)
WaitNamedPipe(_T("\\\\.\\pipe\\chenxiao"),0);
這個(gè)函數(shù)呢就屬于一個(gè)查看函數(shù),看看有沒有叫chenxiao的命名管道
大家不要認(rèn)為這個(gè)函數(shù)可以打開命名管道 或者連接管道
大家從msdn上可以看到這句話If the function succeeds,the process should use the CreateFile function to open a handle to the named pipe
今天我由于沒看到這句話苦苦弄了一個(gè)下午也沒連上管道5555555555
在客戶端可以用waitnamedpipe檢查下有沒有這個(gè)管道 然后再createfile打開它。
哦了 搞定了。搞上我的代碼瞅瞅效果。



















































































下圖程序運(yùn)行效果圖
哇卡卡阿卡
posted on 2011-08-01 22:14 陳曉 閱讀(5354) 評(píng)論(6) 編輯 收藏 引用