1. 程式人生 > >MFC:多執行緒和網路多執行緒程式設計舉例

MFC:多執行緒和網路多執行緒程式設計舉例

<span style="font-size:14px;">						
<span style="white-space:pre">								</span>多執行緒程式設計簡例:
HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpsa,     //NULL,使用預設的安全性
  DWORD cbStack,		//0,使用和呼叫執行緒一樣的大小 
  LPTHREAD_START_ROUTINE lpStartAddr,  //執行緒的入口函式地址ThreadProc
  LPVOID lpvThreadParam,    //執行緒引數
  DWORD fdwCreate,      //CREATE_SUSPENDED:執行緒建立後不會執行,直到呼叫ResumeThread;0:建立後立即執行。
  LPDWORD lpIDThread    //返回執行緒ID,可以為NULL.
);
DWORD WINAPI ThreadProc(
  LPVOID lpParameter
);
HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTES lpMutexAttributes, //安全屬性
  BOOL bInitialOwner, //互斥物件的初始擁有者(若為true,需要釋放:誰擁有互斥物件誰釋放)
  LPCTSTR lpName   //互斥物件的名字
);
//互斥物件屬於核心物件,能夠確保執行緒擁有對單個資源的互斥訪問權。
//互斥物件包含一個使用計數,一個執行緒ID。
//若互斥物件已經存在,返回存在的控制代碼,呼叫GetLastError()會返回ERROR_ALREADY_EXISTS
DWORD WaitForSingleObject(
  HANDLE hHandle,  //互斥物件控制代碼,若是有訊號狀態,函式返回;反之,等待
  DWORD dwMilliseconds //超時的時間間隔,若時間到,函式返回,即使沒訊號;0/INFINITE
);
//當擁有互斥物件的執行緒請求時,即使是未通知狀態,也能請求到,此時使用計數加一
BOOL ReleaseMutex(
  HANDLE hMutex
);
//當執行緒終止時,即使沒有釋放,作業系統也會將此訊號量的執行緒ID設為0,引用計數設為0
/**************************************************************************************************************/
				eg:多執行緒舉例//win32控制檯應用程式
#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI Fun1Proc(
  LPVOID lpParameter
);
DWORD WINAPI Fun2Proc(
  LPVOID lpParameter
);
int index = 0;
int tickets = 100;
HANDLE hMutex;
void main(){ 
	HANDLE hThread1;
	HANDLE hThread2;
	hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
	hThread2 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
	CloseHandle(hThread1); //執行緒核心物件的引用計數減一
	CloseHandle(hThread2);
	hMutex = CreateMutex(NULL,FALSE,"tickets"); //建立一個命名的互斥物件
	if(hMutex){  		//如果此互斥物件已經存在
		if(ERROR_ALREADY_EXISTS == GetLastError()){
			cout << "only one instance can run!" << endl;//只能有一個例項
			return ;
		}
	}
	Sleep(4000);//保持主執行緒不要退出,並且不佔用CPU時間
}
DWORD WINAPI Fun1Proc(
			LPVOID lpParameter
		  ){
	while(true){ //讓執行緒不斷迴圈,否則執行緒函式執行完執行緒就退出了
		WaitForSingleObject(hMutex,INFINITE);//注意位置
		if(tickets > 0){ //若在if語句執行時時間片到,會出現一個座位有兩張票情況
			Sleep(1);	//所以要處理執行緒間的同步互斥:CreateMutex()
			cout<< "thread1 sell ticket : " << tickets-- << endl;
		}else
			break;
		ReleaseMutex(hMutex);//將執行緒ID設為0,互斥物件設為已通知狀態
	}
	return 0;
}
DWORD WINAPI Fun2Proc(
			LPVOID lpParameter
		){
	while(true){ 
		WaitForSingleObject(hMutex,INFINITE);
		if(tickets > 0){
			Sleep(1);
			cout<< "thread2 sell ticket : " << tickets-- << endl;
		}else
			break;
		ReleaseMutex(hMutex);
	}
	return 0;
}
/**************************************************************************************************************/
				多執行緒編寫網路聊天室程式(MFC):
程式介面如圖:
<img src="https://img-blog.csdn.net/20141011134431281?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDAwMjcwNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
一、載入套接字
BOOL AfxSocketInit(  //MFC提供的載入套接字型檔1.1版本的函式,用於版本協商
   WSADATA* lpwsaData = NULL  
); 
//Call this function in your CWinApp::InitInstance override to initialize Windows Sockets.
//需要包含標頭檔案: #include <Afxsock.h>
//載入1.1版本的套接字型檔
struct WSAData { 
   WORD wVersion; 
   WORD wHighVersion; 
   char szDescription[WSADESCRIPTION_LEN+1]; 
   char szSystemStatus[WSASYSSTATUS_LEN+1]; 
   unsigned short iMaxSockets; 
   unsigned short iMaxUdpDg; 
   char FAR * lpVendorInfo; 
};
//If lpwsaData is not equal to NULL, then the address of the WSADATA structure is filled by the call to WSAStartup. 
//This function also ensures that WSACleanup is called for you before the application terminates.
二、初始化套接字:1、建立套接字 2、繫結套接字
BOOL CChatDlg::initSocket() //在OnInitDialog中呼叫
{
	m_socket = socket(AF_INET,SOCK_DGRAM,0); //建立套接字
	if(INVALID_SOCKET == m_socket){
		MessageBox("套接字建立失敗");
		return false;
	}
	SOCKADDR_IN addrSock;
	addrSock.sin_family = AF_INET;
	addrSock.sin_port = htons(6000);
	addrSock.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	int retval;
	retval = bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));//繫結套接字
	if(SOCKET_ERROR == retval){
		closesocket(m_socket);
		MessageBox("繫結失敗!");
		return false;
	}
	return true;
}
三、編寫接收端程式(1、建立接收執行緒 2、編寫執行緒函式(接收訊息,給對話方塊post訊息) 3、訊息響應函式)
//在CChatDialog標頭檔案中定義結構體:
struct RECVPARAM{
	SOCKET sock;
	HWND hwnd;`f
};
//在OnInitDialog中:
initSocket();
RECVPARAM*pRecvParam = new RECVPARAM;
pRecvParam->sock = m_socket;
pRecvParam->hwnd = m_hWnd; //對話方塊控制代碼
HANDLE  hThread = CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL); //建立接收執行緒
CloseHandle(hThread); 
//定義靜態的執行緒函式(成員函式)
static DWORD WINAPI RecvProc(LPVOID lpParameter);
DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)//線上程函式裡接收訊息
{
	SOCKET sock = ((RECVPARAM*)lpParameter)->sock;
	HWND hwnd = ((RECVPARAM*)lpParameter)->hwnd;
	SOCKADDR_IN addrFrom; //接收發送端的地址資訊
	int len = sizeof(SOCKADDR);//必須初始化
	char recvBuf[200];
	char tempBuf[300];
	int retval;
	while(true){
		retval = recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);//接收資訊
		if(SOCKET_ERROR == retval)
			break;
		sprintf(tempBuf,"%s say:%s",inet_ntoa(addrFrom.sin_addr),recvBuf);
		::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf); //給對話方塊傳送訊息
	}
	return 0;
}
//1、在CChatDialog標頭檔案中定義訊息的值:
#define WM_RECVDATA WM_USER+1
//2、標頭檔案保護程式碼的註釋巨集之間新增訊息響應函式原型的宣告:
afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);
//3、原始檔訊息對映巨集之間新增訊息對映:
ON_MESSAGE(WM_RECVDATA,OnRecvData) //後面不要加分號
//4、最後,訊息響應函式的實現:
void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lparam){
	CString str = (char*)lparam;
	CString strTemp; //儲存以前接受到的資料
	GetDlgItemText(IDC_EDIT_RECV,strTemp);
	str += "\r\n"; //新增換行
	str += strTemp;
	SetDlgItemText(IDC_EDIT_RECV,str);
}
四、編寫傳送端程式:1、獲取編輯框文字 2、傳送資料 3、設定編輯框文字
void CChatDlg::OnBtnSend() //將“傳送”按鈕設為預設按鈕
{
	DWORD dwIP;
	((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP); //得到的是主機位元組序
	SOCKADDR_IN addrTo;
	addrTo.sin_family = AF_INET; //地址族
	addrTo.sin_port = htons(6000); //埠號
	addrTo.sin_addr.S_un.S_addr = htonl(dwIP); //轉換成網路位元組序
	CString strSend;
	GetDlgItemText(IDC_EDIT_SEND,strSend);
	sendto(m_socket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR)); //傳送資料
	SetDlgItemText(IDC_EDIT_SEND,"");
}
執行結果:
<img src="https://img-blog.csdn.net/20141011134709243?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDAwMjcwNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />



</span>

相關推薦

MFC執行網路執行程式設計舉例

<span style="font-size:14px;"> <span style="white-space:pre"> </span>多執行緒程式設計簡例: HANDLE CreateThread( LPS

JAVA基礎複習(七)執行網路

1、建立執行緒和任務,如: //任務類必須實現Runnable介面 public class TaskClass implements Runnable{ ... public TaskClass(...){ ... } //想要在該執行緒執行的

windows執行網路程式設計

第 10 章  多執行緒與網路程式設計初步  教學提示:Windows 是一個支援多工的作業系統。當在一個程式中需要啟動另外一 個程式時,需要用到多程序的程式設計方式。如果一個程序中有一些相似的任務需要同時推進, 可以為每個任務建立一個執行緒,從而形成多執行緒的程式設計。隨著網路技術的廣泛應用,網路 程式設計

VS2010/MFC入門程式設計十七(執行的建立,包括工作執行使用者介面執行

1.MFC多執行緒簡介 MFC對多執行緒進行了一層簡單的封裝,在Visual C++中每個執行緒都是從CWinThread類繼承而來的。每一個應用程式的執行都有一個主執行緒,這個主執行緒也是從CWinThread類繼承而來的。可以利用CWinThread物件建立應用程式執行的其它執行緒。 MFC用CW

4、執行網路程式設計

知識點:多執行緒與網路程式設計瞭解程序:程序是應用程式執行的例項,有獨立的記憶體空間和系統資源瞭解執行緒:執行緒是CPU排程和分派的基本單位,程序中執行運算的最小單位,真正在CPU上執行的是執行緒main()方法即為主執行緒入口在一個時間只有一個執行緒在執行,採用搶佔資源的方

Java 執行守護執行非守護執行

本文內容大多基於官方文件和網上前輩經驗總結,經過個人實踐加以整理積累,僅供參考。 Java 執行緒分為兩類:使用者執行緒(User Thread)和守護執行緒(Daemon Thread) 守護執行緒的作用是為其他執行緒提供服務,譬如垃圾回收器(GC),

基於Socket的執行非同步非阻塞模式程式設計

      剛開始接觸socket的程式設計的時候,遇到了很多的問題,費了很大勁搞懂。其實往往都是一些比較基本的知識,但是都是很重要的,只要對其熟練的掌握後,相信對基於網路的程式設計會有很大的提高,呵呵。       就拿基於C/S結構的例子來說,我們先看看伺服器和客戶端的流

WPF利用Interactive Data Display實現示波器(C#執行WPF執行

2018.8.7(已實現) 首先,今天還沒有實現示波器,專案中需要這個功能,在探索中有了一點進展,先記錄下來。 實現的chart控制元件,能夠相應滑輪、滑鼠拖動、放大縮小,很適合作為示波器的背景。 關於Interactive Data Display的引用,可以考慮

java執行_守護執行非守護執行

基本概念 守護執行緒:和主執行緒一起結束的執行緒,叫守護執行緒。 非守護執行緒:主執行緒的結束不影響執行緒的執行的執行緒,也叫使用者執行緒。 如何將一個執行緒t變成守護執行緒 呼叫t.setDaemon(true)方法將非守護執行緒變為守護執行緒。

Solaris10 下的執行Mysql執行連線

1. Solairs下的多執行緒 執行緒分成兩種,一種是POSIX格式的(使用 pthread.h),一種是Solairs格式的(thread.h),建議使用 POSIX格式。 int pthread_create(pthread_t *restrict th

Unity人遊戲網路功能(二) 使用網路管理類

[本文翻譯自Unity 5.2的官方文件] NetworkManager是一個可以管理多玩家遊戲的網路狀態的元件。實際上,它是完全用HLAPI實現的,因此開發者可以使用其他的方式實現他的所有功能。然而,NetworkManager把很多有用的功能整合在了一起,

使用UltraEdit配置行註釋取消行註釋

菜單 col 分享圖片 按鍵 ati erl ctrl+s asc Oz UltraEdit功能強大,使用方便,成為軟件開發者必備的文檔和代碼編輯工具。有很多人也直接用它來寫代碼,如C/Java,腳本如:Perl/Tcl/JavaScript 等。如果用來寫代碼,有一個不方

Flutter學習指南檔案、儲存網路

Flutter學習指南 互動、手勢和動畫 UI佈局和控制元件 熟悉Dart語言 編寫第一個應用 開發環境搭建 本篇文章我們先學習 Flutter IO 相關的基礎知識,然後在 Flutter學習指南:互動、手勢和動畫 的基礎上,繼續開發一個 echo 客戶端。由於日常開發中 HTTP 比 socket

Java(三)併發控制5.繼承建立執行實現建立執行之間的區別

這是使用繼承建立的執行緒 class Person extends Thread { private int num=50; public Person(String name) { super(name); } public void run()

hibernate 的的關聯一對的關聯

資料庫的多對多 1.1 資料庫中不能直接對映多對多 處理:建立一個橋接表(中間表),將一個多對多關係轉換成兩個一對多 注1:資料庫多表聯接查詢 永遠就是二個表的聯接查詢 A B C D t1 C t

Linux驅動開發04塊裝置驅動網路裝置驅動

介紹 因為塊裝置驅動和網路裝置驅動實際中用得較少,所以只給出驅動模板,我也沒有具體測試,等到實際用到是再研究吧,溜了溜了。 塊裝置驅動模板 struct xxx_dev { int size; struct request_q

實體類資料庫對一一對對映

用Teacher類和Grade舉例,Teacher類包含grade類的屬性,Grade也包含Teacher類的屬性,但是Grade中的Teaher屬性要用List<Teahcer> 這就是多對一和一對多,實體類程式碼如下: ------------------------------

Java的守護執行非守護執行

一、守護執行緒         java分為兩種執行緒:使用者執行緒和守護執行緒         守護執行緒是指在程式執行的時候在後臺提供一種通用服務的執行緒,比如垃圾回收執行緒就是一個很稱職的守護者,並且這種執

關於Mybatis的對一一對查詢

我們在製作web專案的時候常常會遇到點選查詢詳情資訊或者是顯示多個物件的相同點,這些都可以假想成一堆多或者多對一的情況。 那我們思考一下,能不能在不點選詳情資訊的時候不進行詳情資訊的查詢呢?這樣不是就可以減少資料庫的訪問量,降低記憶體和時間的消耗嗎? 我在使用Mybatis

Java靜態型性動態型性有何區別

靜態多型性指的是程式在編譯時,系統就能決定呼叫哪個函式,如過載。 動態多型性指在執行中才能動態確定操作指標所指的物件,主要通過虛擬函式和重寫來實現。 java 的多型機制遵循一個原則:當父類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成