#include <windows.h>
#include <tchar.h>
#include <windowsX.h>
#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[] = _T("Server Shutdown");
// 服务器线程句柄
HANDLE g_hThreadServer;
///////////////////////////////////////////////////////////////////////////////
// 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
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)
{
SendMessage( hwnd, WM_SETICON, TRUE, (LPARAM)
LoadIcon( (HINSTANCE)hwnd, MAKEINTRESOURCE(IDI_HANDSHAKE) ) );
// Initialize the edit control with some test data request
Edit_SetText( GetDlgItem( hwnd, IDC_REQUEST ), _T("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
//检查服务器线程是否已经终止
DWORD ExitCode;
GetExitCodeThread( g_hThreadServer, &ExitCode );
if ( ExitCode!=STILL_ACTIVE )
{
break;
}
// Copy the request string into the shared data buffer
Edit_GetText( GetDlgItem(hwnd, IDC_REQUEST),
g_szSharedRequestAndResultBuffer,
sizeof(g_szSharedRequestAndResultBuffer) );
// Let the server thread know that a request is ready in the buffer
SetEvent( g_hevtRequestSubmitted );
// Wait for the server to process the request and give us the result
WaitForSingleObject( g_hevtResultReturned, INFINITE );/*如果用户已经发送过终止字符串,则g_hevtResultReturned不会变为通知状态*/
// Let the user know the result
Edit_SetText( GetDlgItem(hwnd, IDC_RESULT),
g_szSharedRequestAndResultBuffer );
break;
}
}
///////////////////////////////////////////////////////////////////////////////
int WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
HANDLE_MSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
HANDLE_MSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
// 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;
g_hThreadServer = CreateThread( NULL, 0, ServerThread, NULL, 0, &dwThreadID );
// Execute the client thread's user-interface
DialogBox( hInstance, MAKEINTRESOURCE(IDD_HANDSHAKE), NULL, Dlg_Proc );
// 检查服务器线程是否已经终止
DWORD ExitCode;
GetExitCodeThread( g_hThreadServer, &ExitCode );
if ( ExitCode!=STILL_ACTIVE )
{
goto _clean_up_everything;
}
// The client's UI is closing, have the server thread shutdown
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] = g_hThreadServer;
WaitForMultipleObjects( 2, h, TRUE, INFINITE );/*如果用户已经发送过终止字符串,则g_hevtResultReturned不会变为通知状态*/
//添加一个标签
_clean_up_everything:
// Properly clean up everything
CloseHandle( g_hThreadServer );
CloseHandle( g_hevtRequestSubmitted );
CloseHandle( g_hevtResultReturned );
// The client thread terminates with the whole process
return 0;
}