/******************************************************************************
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 //////////////////////////////////
 posted on 2009-11-04 15:36  wParma  阅读(926)  评论(2编辑  收藏  举报