多线程命名管道通信的实现
转载自: http://www.cnblogs.com/xinhaijulan/archive/2010/07/31/1789147.html
上篇介绍了【多线程命名管道通信的设计 】,本篇进行多线程命名管道通信的实现。
服务端实现如下:
创建创建命名管道实例线程
代码
// Handle of create Named Pipe thread.
HANDLE hThreadCreatePipes;
// Create Named Pipe thread .
hThreadCreatePipes = CreateThread(
NULL, // no security attribute
0, // default stack size
FUNCreatePipes, // thread proc
this, // thread parameter
0, // not suspended
NULL); // returns thread ID
// Close Handle.
CloseHandle(hThreadCreatePipes);
// Set handle null.
hThreadCreatePipes = NULL;
创建命名管道并创建监听管道线程:
代码
DWORD WINAPI FUNCreatePipes(LPVOID lpParameter);
DWORD WINAPI FUNCreatePipes(LPVOID lpParameter)
{
BOOL fConnected = FALSE;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\MyPipe");
HANDLE hPipeServer;
HANDLE hThreadListenPipes;
while(TRUE)
{
hPipeServer = CreateNamedPipe(
lpszPipename, // pipe name
PIPE_ACCESS_DUPLEX, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZ, // output buffer size
BUFSIZ, // input buffer size
0, // client time-out
NULL); // default security attribute
if (hPipeServer == INVALID_HANDLE_VALUE)
{
AfxMessageBox("Create named pipes failed.");
return -1;
}
// Wait for the client to connect; if it succeeds,
// the function returns a nonzero value. If the function
// returns zero, GetLastError returns ERROR_PIPE_CONNECTED.
fConnected = ConnectNamedPipe(hPipeServer, NULL);
if (fConnected)
{
// Create listen pipes thread.
hThreadListenPipes = CreateThread(
NULL, // no security attribute
0, // default stack size
FunListenPipes, // thread proc
hPipeServer, // thread parameter
0, // not suspended
NULL); // returns thread ID
// Close handle.
CloseHandle(hThreadListenPipes);
// Set handle null.
hThreadListenPipes = NULL;
}
else
{
// Close handle.
CloseHandle(hPipeServer);
// Set handle null.
hPipeServer = NULL;
}
}
return 0;
}
监听管道,对管道数据进行读取与回写:
代码
DWORD WINAPI FunListenPipes(LPVOID lpParameter);
DWORD WINAPI FunListenPipes(LPVOID lpParameter)
{
HANDLE hPipe = (HANDLE)lpParameter;
HANDLE hHeap = GetProcessHeap();
TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZ*sizeof(TCHAR));
TCHAR* pchReply = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZ*sizeof(TCHAR));
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
BOOL fSuccess = FALSE;
CString strRequest = "";
CString strReply = "";
while (TRUE)
{
fSuccess = ReadFile(
hPipe, // handle to pipe
pchRequest, // buffer to receive data
BUFSIZ*sizeof(TCHAR), // size of buffer
&cbBytesRead, // number of bytes read
NULL); // not overlapped I/O
if (!fSuccess || cbBytesRead == 0)
{
break;
}
// Process the incoming message.
GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes);
// Write the reply to the pipe.
fSuccess = WriteFile(
hPipe, // handle to pipe
pchReply, // buffer to write from
cbReplyBytes, // number of bytes to write
&cbWritten, // number of bytes written
NULL); // not overlapped I/O
if (!fSuccess || cbReplyBytes != cbWritten)
{
break;
}
strRequest = pchRequest;
strReply = pchReply;
}
// Flush the pipe to allow the client to read the pipe's contents
// before disconnecting. Then disconnect the pipe, and close the
// handle to this pipe instance.
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
hPipe = NULL;
HeapFree(hHeap, 0, pchRequest);
HeapFree(hHeap, 0, pchReply);
return 1;
}
VOID GetAnswerToRequest( LPTSTR pchRequest, LPTSTR pchReply, LPDWORD pchBytes )
{
// Check the outgoing message to make sure it's not too long for the buffer.
if (FAILED(strcpy(pchReply, pchRequest)))
{
*pchBytes = 0;
pchReply[0] = 0;
return;
}
*pchBytes = (lstrlen(pchReply)+1)*sizeof(TCHAR);
}
服务端采用阻塞模式等待客户端的连接,客户端连接成功后,立即继续等待下一个客户端的连接
并进行管道的监听、管道数据的读取与写入。
以下为客户端实现:
初始化管道:
创建文件
CString strServerIP="This is the server ip";
CString lpPipeName="\\\\" + strServerIP + "\\pipe\\MyPipe";
LPTSTR lpszPipename = new TCHAR[lpPipeName.GetLength()+1];
_tcscpy(lpszPipename, lpPipename);
HANDLE m_hPipeClient = CreateFile(
lpszPipename,
GENERIC_WRITE|GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if(m_hPipeClient == INVALID_HANDLE_VALUE)
{
CString strLastError;
strLastError.Format("%d",GetLastError());
AfxMessageBox("Error open pipes, the Last Error number is:"+strLastError);
return;
}
else
{
AfxMessageBox("Success open pipes");
}
设置管道状态
设置管道状态
DWORD dwMode = PIPE_READMODE_MESSAGE;
BOOL fSuccess = SetNamedPipeHandleState(
m_hPipeClient, // pipe handle
&dwMode, // new pipe mode
NULL, // don't set maximum bytes
NULL); // don't set maximum time
if ( ! fSuccess)
{
AfxMessageBox("Failed SetNamedPipeHandleState");
}
创建N个管道线程
创建N个管道线程
//Set thread number.
int nThreadNumber=10;
HANDLE m_hThreadSendReadData;
for (int i=0;i<nThreadNumber;++i)
{
m_hThreadSendReadData = CreateThread(NULL,0,FunSendReadData,this,0,NULL);
CloseHandle(m_hThreadSendReadData);
m_hThreadSendReadData = NULL;
}
读写管道
读写管道
DWORD WINAPI FunSendReadData(LPVOID lpParameter);
DWORD WINAPI FunSendReadData(LPVOID lpParameter)
{
DWORD dwRead,dwWritten;
TCHAR chBuf[BUFSIZ];
BOOL fSuccess = FALSE;
DWORD cbRead, cbToWrite, cbWritten, dwMode;
LPTSTR lpvMessage=TEXT("This is the data sent.");
while(TRUE)
{
cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);
fSuccess = WriteFile(
pDlg->m_hPipeClient, // pipe handle
lpvMessage, // message
cbToWrite, // message length
&cbWritten, // bytes written
NULL);
if (!fSuccess)
{
break;
}
do
{
// Read from the pipe.
fSuccess = ReadFile(
pDlg->m_hPipeClient, // pipe handle
chBuf, // buffer to receive reply
BUFSIZ*sizeof(TCHAR), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
{
break;
}
} while (!fSuccess); // repeat loop if ERROR_MORE_DATA
}
return 0;
}
服务端采用阻塞模式等待客户端的连接,客户端采用多个线程对管道进行数据读写。
因客户端采用多个线程对管道进行读写,故一个线程读取的数据可能并不是此线程写入数据后,服务端读取此线程刚写入的数据后再写入的数据。也就是客户端多个线程写入与读取的数据可能会串,此理论已经过测试,为解决此问题,可以在客户端写入数据时加标识,服务端读取数据后,再写入的数据带上此标识,客户端读取时可根据此标识来判断是否是写入数据后服务端返回的消息。
多线程命名管道通信的实现相关推荐
- c语言管道通信实例,C语言辅导:VC命名管道通信的实现
无论是SQL Server的用户,还是PB的用户,作为C/S结构开发环境,他们在网络通信的实现上,都有一种共同的方法--命名管道.由于当前操作系统的不惟一性,各个系统都有其独自的通信协议,导致了不同系 ...
- Windows/Linux平台下命名管道通信调用参考
在一些需要传递少量数据的进程通信业务中,采用命名管道通信是一种不错的选择,但是管道通信本身是不跨平台的.如果我们想在不同的平台下使用管道通信就会很麻烦.这里我简单的总结了一下命名管道在windows平 ...
- c语言程序实现进程的管道通信,C 进程间通信--命名管道通信代码实现及其原理图示...
在将这个题目之前大家需要了解几个概念: 进程: 我们可以先看进程的定义:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础: ...
- VC命名管道通信的实现
无论是sql server的用户,还是pb的用户,作为c/s结构开发环境,他们在网络通信的实现上,都有一种共同的方法--命名管道.由于当前操作系统的不惟一性,各个系统都有其独自的通信协议,导致了不同系 ...
- linux 命名管道通信速度,《Linux 进程间通信》命名管道:FIFO
命名管道的主要用途:不相关的进程之间交换数据. 命令行上创建命名管道: $ mkfifo filename 程序中创建命名管道: #include #include int mkfifo(const ...
- 两端同时写命名管道的测试程序
转载请标明是引用于 http://blog.csdn.net/chenyujing1234 欢迎大家拍砖 一. 结论:(1)两端可以同时写管道,是可行的.可见管道是双工的. (2)往管道里写数据,最多 ...
- 操作系统实验四——使用命名管道实现进程通信
操作系统实验四--使用命名管道实现进程通信 一. 实验目的 (1)了解windows系统环境下的进程通讯机制. (2)熟悉Windows系统提供的进程通信API. 二. 实验准备 相关API函数介绍 ...
- 【Linux】进程间通信 - 匿名/命名管道与System V共享内存
目录 前言 一.管道 0.什么是管道 1).管道的概念 2).管道的本质 3).管道指令: "|" 1.匿名管道 1).如何创建匿名管道 2).如何使用匿名管道进行通信 3).匿名 ...
- 【Linux】进程间通信 —— 匿名管道 | 命名管道 | System V | 消息队列 | 共享内存
进程间通信 0. 进程间通信 1. 管道 1.1 匿名管道 1.1.1 匿名管道原理 1.1.2 创建匿名管道pipe 1.1.3 基于匿名管道通信的4种情况5个特点 1.2 命名管道 1.2.1 创 ...
最新文章
- 美国微生物科学院22年院士公布!舒跃龙、黄力、卢洪洲、赵国屏!
- 用ironpython驱动你的计算公式
- freebsd 运维人员
- 原生android 权限管理,Android 权限管理(原生、EasyPermissions、RxPermissions)
- 众里寻 Bug 千百度,蓦然回首,它却在隔壁老张处……
- 职高计算机选修6知识点,(计算机基础考试7.doc
- 软件设计师考试笔记:UML统一建模语言
- 利用Python进行数据分析——重要的Python库介绍
- 混合分布(mixture distribution)
- pcb 理论阻值、 过孔_PCB设计中过孔常用的处理方式
- 中国各种茶叶及功效(绿茶\红茶\花茶\乌龙茶\白茶\砖茶)
- wifidog认证php,ddwrt+wifidog搭建热点认证系统(无线路由器web认证)
- 从“人、货、场”搭建数据指标体系,助力电商增长
- Android实现三角形气泡效果方式汇总,高级安卓面试题及答案2019
- kettle spoon判断增量更新_使用Kettle实现数据实时增量同步--时间戳增量回滚同步...
- 几种常用的像素混合方法
- Vue错误日记 ——关于Vue-Router出现esm-bundler.js?6c02:2127 Uncaught TypeError: Object(...) is no的解决方案
- c语言createfile函数,C语言的下载函数
- 陆金所季报图解:营收173亿同比增14% 八成新增借款流向小微
- 什么是荧光原位杂交(FISH)?
热门文章
- 怎么用nodejs检测网络状态?
- ElasticSearch入门与Sense插件的使用
- 【Linux】文件系统
- Redis分布式集群部署安装及细节(多主机搭建集群开启多个服务)
- Oracle GoldenGate技术
- tf变换及工具说明(1)
- 计算机终端可以在高温高湿的环境下使用,第三章 计算机境安全.ppt
- redis 在windows 上的安装与使用
- 两个字符串的最长公共子序列长度_求2个字符串的最长公共子序列和最长公共子字符串...
- bbr29_单边加速利器TCP BBR 锐速最佳替代品 | 厘米天空