Переглянути джерело

使用多线程测试服务端是否能支持并发。
测试结果:未发现不妥。

Jeff 6 роки тому
батько
коміт
e94f5e28ae
1 змінених файлів з 122 додано та 99 видалено
  1. 122 99
      基础应用/npc/npc/npc.cpp

+ 122 - 99
基础应用/npc/npc/npc.cpp

@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <conio.h>
 #include <tchar.h>
+#include <process.h>
 
 #define BUFSIZE 512
 
@@ -23,135 +24,157 @@ CWinApp theApp;
 
 using namespace std;
 
-int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
-{
-	int nRetCode = 0;
+void StartThreadProc();
+unsigned WINAPI WorkProc(LPVOID lpParam);
 
-	// 初始化 MFC 并在失败时显示错误
-	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+void StartThreadProc()
+{
+	Sleep(3000);
+	// 开30个线程;
+	int nThreadCount = 60;
+	for ( int i = 0; i < nThreadCount; i++ )
 	{
-		// TODO: 更改错误代码以符合您的需要
-		_tprintf(_T("错误: MFC 初始化失败\n"));
-		nRetCode = 1;
+		HANDLE hThread = NULL;
+		unsigned int dwThreadId = 0;
+		hThread = (HANDLE)_beginthreadex(NULL, 0, WorkProc, NULL, NULL, &dwThreadId);
+		CloseHandle(hThread);
 	}
-	else
-	{
-		// TODO: 在此处为应用程序的行为编写代码。
-		HANDLE hPipe; 
-		LPTSTR lpvMessage=TEXT("Default message from client."); 
-		TCHAR  chBuf[BUFSIZE]; 
-		BOOL   fSuccess = FALSE; 
-		DWORD  cbRead, cbToWrite, cbWritten, dwMode; 
-		LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
+}
 
-		if( argc > 1 )
-			lpvMessage = argv[1];
+unsigned WINAPI WorkProc(LPVOID lpParam)
+{
+	HANDLE hPipe; 
+	DWORD dwThreadId = GetCurrentThreadId();
+	//LPTSTR lpvMessage=TEXT("Default message from client."); 
+	TCHAR lpvMessage[MAX_PATH] = {0};
+	_stprintf_s(lpvMessage, _T("Default message from client[%ld]"), dwThreadId);
+	TCHAR  chBuf[BUFSIZE]; 
+	BOOL   fSuccess = FALSE; 
+	DWORD  cbRead, cbToWrite, cbWritten, dwMode; 
+	LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
+
+	// Try to open a named pipe; wait for it, if necessary. 
+
+	while (1) 
+	{ 
+		hPipe = CreateFile( 
+			lpszPipename,   // pipe name 
+			GENERIC_READ |  // read and write access 
+			GENERIC_WRITE, 
+			0,              // no sharing 
+			NULL,           // default security attributes
+			OPEN_EXISTING,  // opens existing pipe 
+			0,              // default attributes 
+			NULL);          // no template file 
+
+		// Break if the pipe handle is valid. 
+
+		if (hPipe != INVALID_HANDLE_VALUE) 
+			break; 
+
+		// Exit if an error other than ERROR_PIPE_BUSY occurs. 
+
+		if (GetLastError() != ERROR_PIPE_BUSY) 
+		{
+			_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() ); 
+			return -1;
+		}
 
-		// Try to open a named pipe; wait for it, if necessary. 
+		// All pipe instances are busy, so wait for 20 seconds. 
 
-		while (1) 
+		if ( ! WaitNamedPipe(lpszPipename, 20000)) 
 		{ 
-			hPipe = CreateFile( 
-				lpszPipename,   // pipe name 
-				GENERIC_READ |  // read and write access 
-				GENERIC_WRITE, 
-				0,              // no sharing 
-				NULL,           // default security attributes
-				OPEN_EXISTING,  // opens existing pipe 
-				0,              // default attributes 
-				NULL);          // no template file 
-
-			// Break if the pipe handle is valid. 
-
-			if (hPipe != INVALID_HANDLE_VALUE) 
-				break; 
-
-			// Exit if an error other than ERROR_PIPE_BUSY occurs. 
-
-			if (GetLastError() != ERROR_PIPE_BUSY) 
-			{
-				_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() ); 
-				return -1;
-			}
-
-			// All pipe instances are busy, so wait for 20 seconds. 
-
-			if ( ! WaitNamedPipe(lpszPipename, 20000)) 
-			{ 
-				printf("Could not open pipe: 20 second wait timed out."); 
-				return -1;
-			} 
+			printf("Could not open pipe: 20 second wait timed out."); 
+			return -1;
 		} 
+	} 
 
-		// The pipe connected; change to message-read mode. 
+	// The pipe connected; change to message-read mode. 
 
-		dwMode = PIPE_READMODE_MESSAGE; 
-		fSuccess = SetNamedPipeHandleState( 
-			hPipe,    // pipe handle 
-			&dwMode,  // new pipe mode 
-			NULL,     // don't set maximum bytes 
-			NULL);    // don't set maximum time 
-		if ( ! fSuccess) 
-		{
-			_tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); 
-			return -1;
-		}
+	dwMode = PIPE_READMODE_MESSAGE; 
+	fSuccess = SetNamedPipeHandleState( 
+		hPipe,    // pipe handle 
+		&dwMode,  // new pipe mode 
+		NULL,     // don't set maximum bytes 
+		NULL);    // don't set maximum time 
+	if ( ! fSuccess) 
+	{
+		_tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); 
+		return -1;
+	}
 
-		// Send a message to the pipe server. 
+	// Send a message to the pipe server. 
 
-		cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);
-		_tprintf( TEXT("Sending %d byte message: \"%s\"\n"), cbToWrite, lpvMessage); 
+	cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);
+	_tprintf( TEXT("Sending %d byte message: \"%s\"\n"), cbToWrite, lpvMessage); 
 
-		for (int i = 0; i <1000; i++)
-		{
-			fSuccess = WriteFile( 
+	for (int i = 0; i <1000; i++)
+	{
+		fSuccess = WriteFile( 
 			hPipe,                  // pipe handle 
 			lpvMessage,             // message 
 			cbToWrite,              // message length 
 			&cbWritten,             // bytes written 
 			NULL);                  // not overlapped 
 
-			if ( ! fSuccess) 
-			{
-				_tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); 
-				return -1;
-			}
-
-			printf("\nMessage sent to server, receiving reply as follows:\n");
+		if ( ! fSuccess) 
+		{
+			_tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); 
+			return -1;
+		}
 
-			do 
-			{ 
-				// Read from the pipe. 
+		printf("\nMessage sent to server, receiving reply as follows:\n");
 
-				fSuccess = ReadFile( 
-					hPipe,    // pipe handle 
-					chBuf,    // buffer to receive reply 
-					BUFSIZE*sizeof(TCHAR),  // size of buffer 
-					&cbRead,  // number of bytes read 
-					NULL);    // not overlapped 
+		do 
+		{ 
+			// Read from the pipe. 
 
-				if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
-					break; 
+			fSuccess = ReadFile( 
+				hPipe,    // pipe handle 
+				chBuf,    // buffer to receive reply 
+				BUFSIZE*sizeof(TCHAR),  // size of buffer 
+				&cbRead,  // number of bytes read 
+				NULL);    // not overlapped 
 
-				_tprintf( TEXT("\"%s\"\n"), chBuf ); 
-			} while ( ! fSuccess);  // repeat loop if ERROR_MORE_DATA 
+			if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
+				break; 
 
-			if ( ! fSuccess)
-			{
-				_tprintf( TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError() );
-				return -1;
-			}
+			_tprintf( TEXT("\"%s\"\n"), chBuf ); 
+		} while ( ! fSuccess);  // repeat loop if ERROR_MORE_DATA 
 
-			Sleep(100);
+		if ( ! fSuccess)
+		{
+			_tprintf( TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError() );
+			return -1;
 		}
 
-		printf("\n<End of message, press ENTER to terminate connection and exit>");
-		_getch();
+		Sleep(100);
+	}
+
+	printf("\n<End of message, press ENTER to terminate connection and exit>");
+	_getch();
+
+	CloseHandle(hPipe); 
 
-		CloseHandle(hPipe); 
+	return 0; 
+}
 
-		return 0; 
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+	int nRetCode = 0;
 
+	// 初始化 MFC 并在失败时显示错误
+	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+	{
+		// TODO: 更改错误代码以符合您的需要
+		_tprintf(_T("错误: MFC 初始化失败\n"));
+		nRetCode = 1;
+	}
+	else
+	{
+		// TODO: 在此处为应用程序的行为编写代码。
+		StartThreadProc();
+		system("pause");
 	}
 
 	return nRetCode;