多线程服务器进程的这个例子有一个主线程不断循环,创建管道实例并等待客户端进程连接。当客户端进程连接时,服务器进程创建一个线程来为该客户端提供服务,循环重新开始。客户端进程可以在调用CreateNamedPipe和ConnectNamedPipe函数之间的时间间隔内成功连接到管道实例。如果发生这种情况,ConnectNamedPipe返回FALSE,GetLastError返回ERROR_PIPE_CONNECTED。
创建为为每个管道实例服务的线程从管道读取请求,并将回复写入管道,直到客户端进程关闭其句柄。当这种情况发生时,螺纹冲洗管道,断开连接,关闭管道手柄并终止。
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < windows.h >
VOID InstanceThread(LPVOID);
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD);
int xx = 0;
DWORD主(VOID)
{
BOOL fConnected;
DWORD dwThreadId;
HANDLE hPipe, hThread;
LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe";
//主循环创建一个命名管道的实例
//然后等待客户端连接到它。当客户端
//连接,创建一个线程来处理通信
//与该客户端,并重复循环。
for (;;)
{
hPipe = CreateNamedPipe(
lpszPipename, //管道名称
PIPE_ACCESS_DUPLEX, //读/写访问
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | //消息读取模式
PIPE_WAIT, //阻止模式
PIPE_UNLIMITED_INSTANCES, //最大实例
BUFSIZE, //输出缓冲区大小
BUFSIZE, //输入缓冲区大小
PIPE_TIMEOUT, //客户端超时
NULL); //没有安全属性
if (hPipe == INVALID_HANDLE_VALUE)
MyErrExit("CreatePipe");
//等待客户端连接;如果成功,
//函数返回TRUE。如果函数返回FALSE,
// GetLastError返回ERROR_PIPE_CONNECTED。
fConnected = ConnectNamedPipe(hPipe, NULL) ?
TRUE :
(GetLastError() == ERROR_PIPE_CONNECTED);
if(fConnected)
{
//为此客户端创建一个线程。
hThread = CreateThread(
NULL, //无安全属性
0, //默认堆栈大小
(LPTHREAD_START_ROUTINE)InstanceThread,
(LPVOID) hPipe, //线程参数
0, //未暂停
&dwThreadId); //返回线程ID
if (hThread == INVALID_HANDLE_VALUE)
MyErrExit("CreateThread");
}
其他
//客户端无法连接,因此关闭管道。
CloseHandle(hPipe);
}
return 1;
}
VOID InstanceThread(LPVOID lpvParam)
{
CHAR chRequest[BUFSIZE];
CHAR chReply[BUFSIZE];
DWORD cbBytesRead, cbReplyBytes, cbWritten;
BOOL fSuccess;
HANDLE hPipe;
//线程参数是管道实例的句柄。
hPipe = (HANDLE) lpvParam;
而(1)
{
//从管道读取客户端请求。
fSuccess = ReadFile(
hPipe, //处理管道
chRequest, //缓冲区接收数据
BUFSIZE, //缓冲区大小
&cbBytesRead, //读取的字节数
NULL); //不重叠I / O
if (! fSuccess || cbBytesRead == 0)
break;
GetAnswerToRequest(chRequest, chReply, &cbReplyBytes);
//将回复写入管道。
fSuccess = WriteFile(
hPipe, //处理管道
chReply, //缓冲区写入
cbReplyBytes, //要写入的字节数
&cbWritten, //写入的字节数
NULL); //不重叠I / O
if (! fSuccess || cbReplyBytes != cbWritten) break;
}
//刷新管道以允许客户端读取管道的内容
//断开连接前。然后断开管道,并关闭
//这个管道实例的句柄。
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
}