/******************************************************************************
Module: Handshake.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/
#include "..\CmnHdr.h" /* See Appendix A. */
#include <windowsx.h>
#include <tchar.h>
#include <process.h> // For beginthreadex
#include "Resource.h"
///////////////////////////////////////////////////////////////////////////////
// This event is signaled when the client has a request for the server
// 当客户端从服务器返回时该事件被通知(客户端将字符放入共享缓存时被通知)
HANDLE g_hevtRequestSubmitted;
// This event is signaled when the server has a result for the client
// 当服务器完成翻转字符串时该事件被通知
HANDLE g_hevtResultReturned;
// The buffer shared between the client and server threads
// 客户端和服务器共享的缓存区
TCHAR g_szSharedRequestAndResultBuffer[1024];
// The special value sent from the client that causes the
// server thread to terminate cleanly.
// 客户端发送这个指定的值导致服务端线程终止
TCHAR g_szServerShutdown[] = TEXT("Server Shutdown");
///////////////////////////////////////////////////////////////////////////////
// This is the code executed by the server thread
// 这些代码被服务器端线程执行
DWORD WINAPI ServerThread(PVOID pvParam) {
// Assume that the server thread is to run forever
//假设服务器端线程不会永远执行
BOOL fShutdown = FALSE;
while (!fShutdown) {
// Wait for the client to submit a request
//等待事件对象通知
WaitForSingleObject(g_hevtRequestSubmitted, INFINITE);
// Check to see if the client wants the server to terminate
// 读取共享缓存区的值并与g_szServerShutdown比较,判断客户端线程是否要求服务器端线程终止运行
fShutdown =
(lstrcmpi(g_szSharedRequestAndResultBuffer, g_szServerShutdown) == 0);
//如果不是预定义的字符被传入,那么将进行翻转处理
if (!fShutdown) {
// Process the client's request (reverse the string)
_tcsrev(g_szSharedRequestAndResultBuffer);
}
// Let the client process the request's result
//翻转处理完成,通知客户端线程来读取共享缓存区的内容
SetEvent(g_hevtResultReturned);
}
// The client wants us to shutdown, exit
return(0);
}
///////////////////////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) {
//一个该死的宏,用来设置程序图标
chSETDLGICONS(hwnd, IDI_HANDSHAKE);
// Initialize the edit control with some test data request
//也是一个宏..用于设置文本框的初始值
Edit_SetText(GetDlgItem(hwnd, IDC_REQUEST), TEXT("Some test data"));
return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {
switch (id) {
//消息处理退出消息
case IDCANCEL:
EndDialog(hwnd, id);
break;
//处理按钮点击消息
case IDC_SUBMIT: // Submit a request to the server thread
// Copy the request string into the shared data buffer
//获取文本框的值,第一个参数句柄,第二个缓存区,第三个要获取的长度
Edit_GetText(GetDlgItem(hwnd, IDC_REQUEST),
g_szSharedRequestAndResultBuffer,
chDIMOF(g_szSharedRequestAndResultBuffer));
// Let the server thread know that a request is ready in the buffer
//将g_hevtRequestSubmitted置为通知状态使客户端线程可以读取缓存区内容
SetEvent(g_hevtRequestSubmitted);
// Wait for the server to process the request and give us the result
//等待服务器端线程翻转成功的事件通知并将结果文本框内容更新
WaitForSingleObject(g_hevtResultReturned, INFINITE);
// Let the user know the result
Edit_SetText(GetDlgItem(hwnd, IDC_RESULT),
g_szSharedRequestAndResultBuffer);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
///////////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) {
// Create & initialize the 2 nonsignaled, auto-reset events
//自动重置的未通知状态的事件对象
g_hevtRequestSubmitted = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hevtResultReturned = CreateEvent(NULL, FALSE, FALSE, NULL);
// Spawn the server thread
//创建服务器线程
DWORD dwThreadID;
HANDLE hThreadServer = chBEGINTHREADEX(NULL, 0, ServerThread, NULL,
0, &dwThreadID);
// Execute the client thread's user-interface
//哈哈这是一个模态的对话框,运行客户端线程的用户界面。
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_HANDSHAKE), NULL, Dlg_Proc);
// The client's UI is closing, have the server thread shutdown
// 模态对话框退出以后,向服务器线程发送g_szServerShutdown
// 并将g_hevtRequestSubmitted事件设为通知状态让服务器端线程运行(退出的代码)
lstrcpy(g_szSharedRequestAndResultBuffer, g_szServerShutdown);
SetEvent(g_hevtRequestSubmitted);
// Wait for the server thread to acknowledge the shutdown AND
// wait for the server thread to fully terminate
// 等待服务器线程得到关闭通知并且完全关闭
HANDLE h[2];
h[0] = g_hevtResultReturned;
h[1] = hThreadServer;
WaitForMultipleObjects(2, h, TRUE, INFINITE);
// Properly clean up everything
CloseHandle(hThreadServer);
//此时g_hevtRequestSubmitted依然为未通知状态因为是自动重置事件对象
//当服务器线程结束的时候它的内核对象变为通知状态,并且这种过程是不可逆的。
CloseHandle(g_hevtRequestSubmitted);
CloseHandle(g_hevtResultReturned);
// The client thread terminates with the whole process
return(0);
}
//////////////////////////////// End of File //////////////////////////////////
Module: Handshake.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/
#include "..\CmnHdr.h" /* See Appendix A. */
#include <windowsx.h>
#include <tchar.h>
#include <process.h> // For beginthreadex
#include "Resource.h"
///////////////////////////////////////////////////////////////////////////////
// This event is signaled when the client has a request for the server
// 当客户端从服务器返回时该事件被通知(客户端将字符放入共享缓存时被通知)
HANDLE g_hevtRequestSubmitted;
// This event is signaled when the server has a result for the client
// 当服务器完成翻转字符串时该事件被通知
HANDLE g_hevtResultReturned;
// The buffer shared between the client and server threads
// 客户端和服务器共享的缓存区
TCHAR g_szSharedRequestAndResultBuffer[1024];
// The special value sent from the client that causes the
// server thread to terminate cleanly.
// 客户端发送这个指定的值导致服务端线程终止
TCHAR g_szServerShutdown[] = TEXT("Server Shutdown");
///////////////////////////////////////////////////////////////////////////////
// This is the code executed by the server thread
// 这些代码被服务器端线程执行
DWORD WINAPI ServerThread(PVOID pvParam) {
// Assume that the server thread is to run forever
//假设服务器端线程不会永远执行
BOOL fShutdown = FALSE;
while (!fShutdown) {
// Wait for the client to submit a request
//等待事件对象通知
WaitForSingleObject(g_hevtRequestSubmitted, INFINITE);
// Check to see if the client wants the server to terminate
// 读取共享缓存区的值并与g_szServerShutdown比较,判断客户端线程是否要求服务器端线程终止运行
fShutdown =
(lstrcmpi(g_szSharedRequestAndResultBuffer, g_szServerShutdown) == 0);
//如果不是预定义的字符被传入,那么将进行翻转处理
if (!fShutdown) {
// Process the client's request (reverse the string)
_tcsrev(g_szSharedRequestAndResultBuffer);
}
// Let the client process the request's result
//翻转处理完成,通知客户端线程来读取共享缓存区的内容
SetEvent(g_hevtResultReturned);
}
// The client wants us to shutdown, exit
return(0);
}
///////////////////////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) {
//一个该死的宏,用来设置程序图标
chSETDLGICONS(hwnd, IDI_HANDSHAKE);
// Initialize the edit control with some test data request
//也是一个宏..用于设置文本框的初始值
Edit_SetText(GetDlgItem(hwnd, IDC_REQUEST), TEXT("Some test data"));
return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {
switch (id) {
//消息处理退出消息
case IDCANCEL:
EndDialog(hwnd, id);
break;
//处理按钮点击消息
case IDC_SUBMIT: // Submit a request to the server thread
// Copy the request string into the shared data buffer
//获取文本框的值,第一个参数句柄,第二个缓存区,第三个要获取的长度
Edit_GetText(GetDlgItem(hwnd, IDC_REQUEST),
g_szSharedRequestAndResultBuffer,
chDIMOF(g_szSharedRequestAndResultBuffer));
// Let the server thread know that a request is ready in the buffer
//将g_hevtRequestSubmitted置为通知状态使客户端线程可以读取缓存区内容
SetEvent(g_hevtRequestSubmitted);
// Wait for the server to process the request and give us the result
//等待服务器端线程翻转成功的事件通知并将结果文本框内容更新
WaitForSingleObject(g_hevtResultReturned, INFINITE);
// Let the user know the result
Edit_SetText(GetDlgItem(hwnd, IDC_RESULT),
g_szSharedRequestAndResultBuffer);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
///////////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) {
// Create & initialize the 2 nonsignaled, auto-reset events
//自动重置的未通知状态的事件对象
g_hevtRequestSubmitted = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hevtResultReturned = CreateEvent(NULL, FALSE, FALSE, NULL);
// Spawn the server thread
//创建服务器线程
DWORD dwThreadID;
HANDLE hThreadServer = chBEGINTHREADEX(NULL, 0, ServerThread, NULL,
0, &dwThreadID);
// Execute the client thread's user-interface
//哈哈这是一个模态的对话框,运行客户端线程的用户界面。
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_HANDSHAKE), NULL, Dlg_Proc);
// The client's UI is closing, have the server thread shutdown
// 模态对话框退出以后,向服务器线程发送g_szServerShutdown
// 并将g_hevtRequestSubmitted事件设为通知状态让服务器端线程运行(退出的代码)
lstrcpy(g_szSharedRequestAndResultBuffer, g_szServerShutdown);
SetEvent(g_hevtRequestSubmitted);
// Wait for the server thread to acknowledge the shutdown AND
// wait for the server thread to fully terminate
// 等待服务器线程得到关闭通知并且完全关闭
HANDLE h[2];
h[0] = g_hevtResultReturned;
h[1] = hThreadServer;
WaitForMultipleObjects(2, h, TRUE, INFINITE);
// Properly clean up everything
CloseHandle(hThreadServer);
//此时g_hevtRequestSubmitted依然为未通知状态因为是自动重置事件对象
//当服务器线程结束的时候它的内核对象变为通知状态,并且这种过程是不可逆的。
CloseHandle(g_hevtRequestSubmitted);
CloseHandle(g_hevtResultReturned);
// The client thread terminates with the whole process
return(0);
}
//////////////////////////////// End of File //////////////////////////////////