利用命名管道实现进程间通讯

本文介绍了一个使用Windows命名管道实现服务器与客户端通信的应用案例。通过创建多个管道实例并为每个实例分配独立线程的方式,实现了服务器同时处理多个客户端请求的能力。文章详细展示了如何利用重叠I/O机制来提高通信效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

管道服务器创建管道,管道客户端连接管道。

32位,64位之间可以混合通信,主要代码如下:

void CServerDlg::OnBnClickedButtonStartServer()
{
	UpdateData(TRUE);
	CString PipeFullPathData = L"\\\\.\\Pipe\\NamedPipePipe";


	if (m_CEdit_Max_Connect_Count > 0 && m_CEdit_Max_Connect_Count < 100)
	{
		for (UINT i = 0; i < m_CEdit_Max_Connect_Count; i++)
		{
			// 创建管道实例
			m_UserData[i].PipeHandle = CreateNamedPipe(PipeFullPathData, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, \
				PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, m_CEdit_Max_Connect_Count, 0, 0, 1000, NULL);
			if (m_UserData[i].PipeHandle == INVALID_HANDLE_VALUE)
			{
				DWORD ErrorCode = GetLastError();
				this->MessageBox(L"创建管道错误!");
				return;
			}
			// 为每个管道实例创建一个事件对象,用于实现重叠IO
			m_UserData[i].EventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
			// 为每个管道实例分配一个线程,用于响应客户端的请求
			m_UserData[i].ThreadHandle = AfxBeginThread(ThreadProcedure, &m_UserData[i], THREAD_PRIORITY_NORMAL);
		}

		{
			this->SetWindowText(L"命名管道—服务器(运行)");
			this->MessageBox(L"服务启动成功");
		}
	}




	

}


void CServerDlg::OnBnClickedButtonStopServer()
{

	DWORD dwNewMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT;
	for (UINT i = 0; i < m_CEdit_Max_Connect_Count; i++)
	{
		// 设置重叠I/O的事件,使得工作线程安全结束
		SetEvent(m_UserData[i].EventHandle);
		Sleep(1);
		CloseHandle(m_UserData[i].ThreadHandle);
		CloseHandle(m_UserData[i].PipeHandle);
	}

	this->SetWindowText(L"命名管道—服务器(停止)");
	this->MessageBox(L"停止启动成功");
}
UINT ThreadProcedure(LPVOID ParameterData)
{
	DWORD  ReturnLength = 0;
	char   BufferData[0x400] = { 0 };
	
	USER_DATA  UserData = *(USER_DATA*)ParameterData;
	OVERLAPPED Overlapped = { 0, 0, 0, 0, UserData.EventHandle};
	
	while (1)
	{
		memset(BufferData, 0, sizeof(BufferData));
		// 命名管道的连接函数,等待客户端的连接(只针对NT)
		ConnectNamedPipe(UserData.PipeHandle, &Overlapped);
		
		// 实现重叠I/0,等待OVERLAPPED结构的事件对象
		WaitForSingleObject(UserData.EventHandle, INFINITE);
		
		// 检测I/0是否已经完成,如果未完成,意味着该事件对象是人工设置,即服务需要停止
		if (!GetOverlappedResult(UserData.PipeHandle, &Overlapped, &ReturnLength, true))
			break;
		// 从管道中读取客户端的请求信息
		if (!ReadFile(UserData.PipeHandle, BufferData, 0x400, &ReturnLength, NULL))
		{
			MessageBox(0, L"读取管道错误!", 0, 0);
			break;
		}
		int v1, v2;
		sscanf(BufferData, "%d %d", &v1, &v2);  //字符串转换为%d
		__ServerDlg->m_v1  =  v1;
		__ServerDlg->m_v2  =  v2;
		__ServerDlg->m_v3  = v1 + v2;
		memset(BufferData, 0, sizeof(BufferData));
		sprintf(BufferData, "%d", __ServerDlg->m_v3);
		// 把反馈信息写入管道
		WriteFile(UserData.PipeHandle, BufferData, strlen(BufferData), &ReturnLength, NULL);
		__ServerDlg->SetDlgItemInt(IDC_EDIT_V1, v1, true);
		__ServerDlg->SetDlgItemInt(IDC_EDIT_V2, v2, true);
		__ServerDlg->SetDlgItemInt(IDC_EDIT_V3, __ServerDlg->m_v3, true);
		// 断开客户端的连接,以便等待下一客户的到来
		DisconnectNamedPipe(UserData.PipeHandle);
	}

	return 0;
}

void CClientDlg::OnBnClickedButtonSubmitClient()
{
	// TODO: 在此添加控件通知处理程序代码

	HANDLE NamedPipeHandle = CreateFile(L"\\\\.\\Pipe\\NamedPipePipe", GENERIC_READ | GENERIC_WRITE, \
		0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (NamedPipeHandle == INVALID_HANDLE_VALUE)
	{
		this->MessageBox(L"打开管道失败,服务器尚未启动,或者客户端数量过多");
		return;
	}

	DWORD ReturnLength = 0;
	char BufferData[0x400] = { 0 };
	// 把两个整数(a,b)格式化为字符串

	m_v1 = GetDlgItemInt(IDC_EDIT_V1);
	m_v2 = GetDlgItemInt(IDC_EDIT_V2);
	sprintf(BufferData, "%d %d", this->m_v1, this->m_v2);
	// 把数据写入管道
	WriteFile(NamedPipeHandle, BufferData, strlen(BufferData), &ReturnLength, NULL);

	memset(BufferData, 0,0x400);
	// 读取服务器的反馈信息
	ReadFile(NamedPipeHandle, BufferData, 0x400, &ReturnLength, NULL);
	sscanf(BufferData, "%d", &(this->m_v3));
	SetDlgItemInt(IDC_EDIT_V3, m_v3, true);
	
	CloseHandle(NamedPipeHandle);
}
//清空
void CClientDlg::OnBnClickedButtonEmptyClient()
{
	// TODO: 在此添加控件通知处理程序代码
	this->SetDlgItemInt(IDC_EDIT_V1, NULL, true);
	this->SetDlgItemInt(IDC_EDIT_V2, NULL, true);
	this->SetDlgItemInt(IDC_EDIT_V3, NULL, true);
}



界面效果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值