最近實現乙個遠端超級終端的功能,通訊模式是這樣的:
客戶端------通過網路傳送cmd命令到------伺服器端------通過程序間通訊(管道),將此cmd命令發給-----cmd.exe程式,cmd.exe執行此cmd命令
接下來:
cmd.exe------程式將執行結果返回------伺服器端------傳送此次結果到------客戶端,客戶端對結果進行顯示
其中伺服器端程式和cmd.exe程式之間的通訊設計到了程序間的通訊,採用採用匿名雙管道來完成。
管道1:一端:伺服器端寫資料,另一端:cmd.exe讀資料
管道2:一端:伺服器端讀資料,另一端:cmd.exe寫資料
匿名管道的3個特點:
1、只能實現本地機器上的兩個程序之間的通訊,所以伺服器端程式和cmd.exe程式需在一台機器上
2、匿名管道通常用來在父程序和子程序之間進行通訊,所以兩個程序如果想要具有父子關係,必須通過父程序呼叫createprocess函式去啟動子程序
3、因為匿名管道沒有名稱,所以只能在父程序呼叫createprocess呼叫子程序時,將管道的讀、寫控制代碼傳遞給子程序
以此例來說明匿名管道的程序間通訊如何編碼:
1、在伺服器程式中建立管道1和2,建立成功後迴圈讀取管道1中的資料,並將讀取到的資料傳送給客戶端:
void cshellinfo::sheelread()
security_attributes sa2;
sa2.nlength=sizeof(security_attributes);
sa2.lpsecuritydescriptor=null;
sa2.binherithandle=true;//必須設定為true,這樣子程序可以繼承父程序的控制代碼
if (!createpipe(&m_hreadpipe,&m_hwritefile,&sa2,0))
/*讀取管道資料,傳送給遠端主機*/
char szbuf[1024]=;
dword dwbytes=0;
while (true)
cmd cmd;
cmd.flag=0;
strcpy_s(cmd.command,sizeof(cmd.command),szbuf);
cmsghead msghead(command,sizeof(cmd));
int nreth=senddata(m_shellsock,(char*)&msghead,sizeof(msghead));
int nretb=senddata(m_shellsock,(char*)&cmd,sizeof(cmd));
if (nreth<=0||nretb<=0)}}
其中:
createpipe()第三個引數是乙個指向security_attributes結構體的指標,檢測返回的控制代碼能否被子程序繼承。以前凡是需要security_attributes指標的地方,我們都設為null,此處這個指標不能再設定為null了,因為匿名管道只能在父子程序之間進行通訊,且管道是父程序建立的,父程序自然能獲得管道的控制代碼,子程序如果想要獲得匿名管道的控制代碼,只能從父程序繼承而來。當父程序和子程序都擁有了匿名管道的控制代碼後,父子程序之間就可以進行通訊了。所以此處我們應該定義乙個security_attributes結構體變數,並將此結構體變數的第三個引數設定為true,true表示父程序返回的控制代碼可以被子程序繼承。
2、建立乙個和父程序通訊的子程序:
void cshellinfo::sheelinit()
; getsystemdirectory(szcmdpath,max_path);
wcscat_s(szcmdpath,_t("\\cmd.exe"));
/*建立子程序*/
if (!createprocess(szcmdpath,null,null,null,true,null,null,null,&m_si,&m_pi))
closehandle( m_pi.hprocess );
closehandle( m_pi.hthread );
}
其中:createprocess()的第乙個引數是:乙個指向null終止的字串,用來指定可執行檔案的名稱,最好是乙個完整路徑;倒數第二個引數m_si:乙個啟動結構startupinfo的指標 ,主要用來指定新程序(子程序)的視窗如何顯示,使用此結構體應該首先為cb成員賦值,表示結構體本身的大小,以位元組為單位。其次為dwflag成員賦值,表明在什麼情況下選擇使用該結構體的哪些成員;最後乙個引數m_pi:指向process_information結構體的指標,用來接收新程序的標識資訊:程序控制代碼、主線程控制代碼、全域性程序識別符號、全域性執行緒識別符號。
補充:當呼叫createprocess()啟動乙個子程序時,他將繼承父程序所有可繼承的已經開啟的控制代碼,但在子程序中無法知道他所繼承的控制代碼中哪乙個是管道的讀控制代碼,哪乙個是管道的寫控制代碼,為了讓子程序從眾多控制代碼中區分出管道的讀、寫控制代碼,必須將子程序的特殊控制代碼設定為管道的讀、寫控制代碼,這裡我們將子程序的標準輸入控制代碼和標準輸出控制代碼分別設定為管道的讀、寫控制代碼,這樣,子程序只要得到了標準的輸入和輸出控制代碼就得到了管道的讀寫控制代碼。
3、伺服器端(父程序)向管道中寫資料:
void cshellinfo::sheelwrite(char* szbuf)
}
通訊完成後,客戶端結果顯示如下:
程序間通訊 匿名管道
1.程序通訊的目的 1 資料傳輸 乙個程序需要將它的資料傳輸給另乙個程序 2 資源共享 多個程序之間共享同樣的資源 3 通知事件 乙個程序需要向另乙個或一組程序傳送訊息,通知它們發生了什麼事情 2.管道 管道是一種程序之間通訊的一種方式,我們把從乙個程序連線到另乙個程序的資料流叫做管道 3.匿名管道...
程序間通訊 匿名管道
使用匿名管道做程序通訊,需要用父程序建立乙個子程序,該子程序的標準輸入輸出控制代碼由父程序指定。無論父程序還是子程序,都可以收發資料,這裡僅演示父程序發資料,子程序列印資料。父程序迴圈從控制台讀資料,並傳送給子程序,子程序用對話方塊列印資料,約定子程序收到 quit 後退出。define crt s...
程序間通訊 匿名管道通訊
將關於匿名管道通訊過程中遇到的問題以及心得總結一下 使用場合 匿名管道通訊對執行緒間通訊和父子程序之間的通訊非常有用 一下 分三部分 1.建立匿名管道 2.建立子程序 1 使用getstdhandle函式獲取標準輸出裝置的控制代碼 2 使用setstdhandle函式將標準輸出到寫匿名管道 3 使用...