多线程服务器

【勇芳软件工作室】汉化HomePreviousNext

多线程服务器进程的这个例子有一个主线程不断循环,创建管道实例并等待客户端进程连接。当客户端进程连接时,服务器进程创建一个线程来为该客户端提供服务,循环重新开始。客户端进程可以在调用CreateNamedPipeConnectNamedPipe函数之间的时间间隔内成功连接到管道实例。如果发生这种情况,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);

}