VC-进程间通信(InterProcess Communication,IPC)
邮槽
创建邮槽的进程是邮槽服务器,得到邮槽句柄,只有通过邮槽句柄才可以读数据。ReadFile(...)
邮槽创建时,邮槽名称必须是如下形式:\\.\mailslot\[path]name
例子:
// MailslotServer.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <atlstr.h> #include <iostream> #define BUF_SIZE 512 int _tmain(int argc, _TCHAR* argv[]) { const TCHAR* name = _T("\\\\.\\mailslot\\slotTest"); HANDLE hSlot = CreateMailslot(name, 0, MAILSLOT_WAIT_FOREVER, NULL); if (INVALID_HANDLE_VALUE == hSlot) { printf("创建邮槽失败。错误代码:%d\n", GetLastError()); return -1; } TCHAR buffer[BUF_SIZE] = { 0 }; DWORD nReadBytes; if (ReadFile(hSlot, buffer, BUF_SIZE-1, &nReadBytes, NULL)) { std::wcout.imbue(std::locale("chs")); std::wcout << (wchar_t*)buffer << std::endl; } return 0; } ////////////////////////////////////////////////// // MailslotClient.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> int _tmain(int argc, _TCHAR* argv[]) { const TCHAR* name = _T("\\\\.\\mailslot\\slotTest"); HANDLE hSlot = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hSlot) { printf("创建客户端邮槽失败。错误代码=%d\n", GetLastError()); return -1; } TCHAR content[] = _T("我是客户端邮槽,向服务器发送测试数据。"); DWORD nBytesWritten; if (!WriteFile(hSlot, content, sizeof(content), &nBytesWritten, NULL)) { printf("向邮槽写入数据失败,错误代码:%d\n", GetLastError()); return -1; } printf("向邮槽写入了%d个字节的数据。\n", nBytesWritten); CloseHandle(hSlot); return 0; }
匿名管道
父子进程通信,可以双向传输,本地进程通信,CreateProcess()中设置可继承句柄 bInheritHandles为TRUE
例子
//// 父进程 void CPipeServerSampleDlg::OnBnClickedButton1() { // 创建匿名管道,创建子进程 SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE}; HANDLE hRead, hWrite; if (!CreatePipe(&hRead, &hWrite, &sa, 0)) { //"创建匿名管道失败" return; } STARTUPINFO si; PROCESS_INFORMATION pi; si.cb = sizeof(si); GetStartupInfo(&si); si.hStdError = hWrite; si.hStdOutput = hWrite;//将子进程的标准输入输出重定向为管道的读写句柄 si.hStdInput = hRead; si.wShowWindow = SW_HIDE;//隐藏窗口运行 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;//开关打开,否则上面是设置无效 TCHAR szCmdLine[] = _T("PipeClientSample.exe"); if (!CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) { //"创建子进程失败" return; } CloseHandle(hWrite); CStringA log; DWORD fileSize = GetFileSize(hRead, NULL);//获取管道中的内容大小 void* buffer = new BYTE[fileSize + 1](); DWORD dwByteReads; if (!ReadFile(hRead, buffer, fileSize, &dwByteReads, NULL)) return;//读取失败 log += (char*)buffer; delete[] buffer; SetDlgItemTextA(this->GetSafeHwnd(), IDC_EDIT1, log); CloseHandle(hRead); } //// 子进程 // PipeClientSample.cpp : 定义控制台应用程序的入口点。 #include <iostream> int main(int argc, char* argv[]) { std::cout << "这是PipeClientSample的标准输出std::cout" << std::endl; std::cerr << "这是PipeClientSample的错误输出std::cerr" << std::endl; return 0; }
命名管道
支持网络进程间通信
// NamedPipeServer.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <iostream> using std::cout; using std::endl; int _tmain(int argc, _TCHAR* argv[]) { const char* szName = "\\\\.\\pipe\\aaa\\bbb\\myPipe"; //创建命名管道 HANDLE hPipe = CreateNamedPipeA(szName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, NULL); if (INVALID_HANDLE_VALUE == hPipe) { return -1; } //等待客户端连接 BOOL bRet = ConnectNamedPipe(hPipe, NULL); //读数据 int nLen = GetFileSize(hPipe, NULL); char* buf = new char[nLen+1]();// DWORD dwBytes; ReadFile(hPipe, buf, nLen, &dwBytes, NULL); cout << "读到的数据:" << buf << endl << "buf's length : " << nLen << " dwBytes : " << dwBytes << endl; delete[] buf; //写数据 char buf2[] = "PipeServer写的数据。"; DWORD dwBytesWritten; WriteFile(hPipe, buf2, sizeof(buf2), &dwBytesWritten, NULL); cout << "写入数据:" << dwBytesWritten << "Bytes" << endl; getchar(); return 0; } //------------------------------------------ // NamedPipeClient.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <iostream> using std::cout; using std::endl; int _tmain(int argc, _TCHAR* argv[]) { const char* szName = "\\\\.\\pipe\\aaa\\bbb\\myPipe"; //连接命名管道 WaitNamedPipeA(szName, NMPWAIT_WAIT_FOREVER); //打开命名管道 HANDLE hPipe = CreateFileA(szName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hPipe) return -1; //写 char buf2[] = "PipeClient写的数据。"; DWORD dwBytesWritten; WriteFile(hPipe, buf2, sizeof(buf2), &dwBytesWritten, NULL); //读 Sleep(100);//为了能Server端写上数据 int nLen = GetFileSize(hPipe, NULL); char* buf = new char[nLen + 1]();// DWORD dwBytes; ReadFile(hPipe, buf, nLen, &dwBytes, NULL); cout << "读到的数据:" << buf << endl << "buf's length : " << nLen << " dwBytes : " << dwBytes << endl; delete[] buf; getchar(); return 0; }
Socket通信
参考:MFC中Socket网络通讯 和 Windows下socket编程(console非MFC)
发送WM_COPYDATA消息
剪切板
填充剪切板(像ctrl+c)
void CClipboardDlg::OnBnClickedButtonSend() { // TODO: 在此添加控件通知处理程序代码 if (OpenClipboard()) { EmptyClipboard(); CString str1; GetDlgItemText(IDC_EDIT_SEND, str1); CStringA str(str1); HANDLE hClip;//保存调用GlobalAlloc()后返回的内存对象地址 char* pBuf;//保存调用GlobalLock后返回的内存地址 DWORD dwBytes = (str.GetLength() + 1)*sizeof(str[0]); hClip = GlobalAlloc(GMEM_MOVEABLE, dwBytes); pBuf = (char*)GlobalLock(hClip); strcpy_s(pBuf, str.GetLength() + 1, str.GetString()); GlobalUnlock(hClip); SetClipboardData(CF_TEXT, hClip); CloseClipboard();//一定要关闭剪切板 } }
获取剪切板内容
void CClipboardDlg::OnBnClickedButtonRecv() { // TODO: 在此添加控件通知处理程序代码 if (OpenClipboard()) { if (IsClipboardFormatAvailable(CF_TEXT)) { HANDLE hClip; char* buf; hClip = GetClipboardData(CF_TEXT); buf = (char*)GlobalLock(hClip); GlobalUnlock(hClip); CString str(buf); SetDlgItemText(IDC_EDIT_RECV, str); } CloseClipboard(); } }
----------------------------------------------------
常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。
昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。