win32程式設計也學習了乙個快乙個月。前段時間自己寫了個基於udp的簡單聊天室程式。在這裡做乙個總結。
首先網路程式設計一般都是基於tcp或udp的。一般聊天室的程式都是基於udp的面向連線的。一般的過程都是於下:
tcp程式設計的伺服器端一般步驟是:
1、建立乙個socket,用函式socket();
2、繫結ip位址、埠等資訊到socket上,用函式bind();
3、開啟監聽,用函式listen();
4、接收客戶端上來的連線,用函式accept();
5、收發資料,用函式send()和recv(),或者read()和write();
6、關閉網路連線;
7、關閉監聽;
tcp程式設計的客戶端一般步驟是:
1、建立乙個socket,用函式socket();
2、設定要連線的對方的ip位址和埠等屬性;
3、連線伺服器,用函式connect();
4、收發資料,用函式send()和recv(),或者read()和write();
5、關閉網路連線;
與之對應的udp程式設計步驟要簡單許多,分別如下:
udp程式設計的伺服器端一般步驟是:
1、建立乙個socket,用函式socket();
2、繫結ip位址、埠等資訊到socket上,用函式bind();
3、迴圈接收資料,用函式recvfrom();
4、關閉網路連線;
udp程式設計的客戶端一般步驟是:
1、建立乙個socket,用函式socket();
2、設定對方的ip位址和埠等屬性;
3、傳送資料,用函式sendto();
4、關閉網路連線;
由於是win32的程式。首先要把軟體模型編輯出來。這裡就不多說了。一般學了的都會。用乙個對話方塊來實現的。
主要有乙個大的編輯框為接收框。乙個稍大的在下面作為傳送編輯框。兩個小的編輯框用來記錄對方的ip和自己的使用者名稱。
當然還有乙個傳送按鈕。如下:
好了,現在就來編輯**了。在編輯**前我們需要的庫是ws2_32.lib和標頭檔案winsock2.h.一定要記得加進去哦。否則就會報錯。首先我們做初始化套接字功能。先申明乙個全域性的wsadata wsdata;的載入ws2_32.lib套接庫的變數。
在對話方塊的initdialog部分加入:
wsastartup(makeword(2,2),&wsadata);
wsastartup是啟動ws2_32.lib庫的函式。makeword是把兩個高位的和地位的數和成乙個dword型別的數。前乙個引數是低位元組。後面的是高位元組。當然這裡你還可以判斷載入是否成功。
然後在全域性的申明乙個socket m_socket 的套接字變數。編寫乙個函式用來初始化套接字和繫結套接字。
bool initsockt(hwnd hwnd)
//初始化位址。
sockaddr_in addr;
addr.sin_addr.s_un.s_addr =htonl(inaddr_any);//位址是乙個結構體。用htonl把它轉化為網路位元組序。
addr.sin_family = af_inet;//位址家族。
addr.sin_port = htons(port);//埠。這個port是自己申明的變數,一般自己申明的埠號要大於1024.同樣用htons轉化網路形式。
int retbind;
//繫結套接字。
retbind = bind(m_socket,(sockaddr*)&addr,sizeof(addr));
if(socket_error == retbind)
setwindowtext(getdlgitem(hwnd,idc_stc),text("繫結套接字成功!")); //同樣成功,在靜態控制項中顯示出來。
return true;
}這個函式作為服務端的初始化。也將放在initdialog裡面來呼叫。
由於這個程式是在乙個對話方塊中實現客戶端和服務端的。所以我們要用到多執行緒的知識。我們要建立乙個執行緒來接收來自服務端和客戶端的資料。
我們還是一樣在初始化對話方塊中來建立執行緒。
handle handle;//執行緒控制代碼。
lpinfo *lpinfo;
lpinfo->hwnd=hwnd;
lpinfo->server=m_socket;
//建立接收端執行緒, 將控制代碼和socket作為結構體變數傳入執行緒函式中。
handle = createthread(null,0,threadfunc,(lpvoid)lpinfo,0,null);
closehandle(handle);//記得關閉執行緒。
建立執行緒函式原型:handlecreatethread(lpsecurity_attributeslpthreadattributes
,size_tdwstacksize
,
lpthread_start_routinelpstartaddress
,
lpvoidlpparameter
,
dworddwcreationflags
,
lpdwordlpthreadid
);
因為我們的執行緒函式將用到視窗的控制代碼和我們剛初始化的套接字作為乙個結構的引數傳入執行緒函式中。
dword winapi threadfunc(lpvoid lp)
執行緒函式只能這麼呼叫。它只有乙個lpvoid的無型別的指標。我們就通過它來傳遞我們需要的資料。因為他是無型別指標。所以我們傳入的時候也採用lpvoid強制轉換一下。關於createthread函式這裡就不多講了。有興趣可以看看多執行緒方面的東西就可以了,可以檢視msdn,要注意的是倒數第二個引數是建立後是否立即執行。為0就立即執行。其實我們剛開始就將m_sock變數作為全域性的變數,這裡可以不用作為引數傳入進去了 。但是我是初學者。要懂得有這樣的方式來傳遞資料。以後就是不能有全域性資料也能一通百通的用了啊。呵呵。
既然建立了執行緒 。我們就來處理執行緒函式吧。為了達到有qq一樣的有使用者名稱和時間,我這裡也呼叫了時間的函式和聲音函式。還要注意的是怎麼樣在編輯框裡面讓它自動的換行。當然你首先在資源編輯裡面屬性裡面就的讓它有換行的功能。然後採用字串後面加/r/n的方式使它每次需要換行的時候自動換行,這樣就實現了qq的方式。函式如下:
dword winapi threadfunc(lpvoid lp)
setwindowtext(getdlgitem(hwnd,idc_stc),text("聊天連線成功!"));
//將時間格式化後存入緩衝區。這裡我還要說明一點。有兩個函式這裡可以實現。
//wsprintf和sprintf。但是他們有區別的。主要是能放的緩衝區大小問題。大家可以去試試他們的區別。
getdlgitemtext(hwnd,idc_edt_use,cusename,sizeof(cusename));
sprintf(tempbuf,"【%s 】/t %s",cusename,cresult);
strcat(tempbuf,"/r/n");//實現自動換行。
strcat(tempbuf,recvbuf);
strcat(tempbuf,"/r/n");//實現自動換行。
getdlgitemtext(hwnd,idc_edt_recv,buff,sizeof(buff));
strcat(buff,tempbuf);
//做好了所以工作後將他們集體輸出到編輯框中。原理是先得到編輯框的內容。在加要輸出的內容。後一起輸出到編輯框。
setdlgitemtext(hwnd,idc_edt_recv,buff);
} return 0;
}注意我們用到聲音的函式。要加入winmm.lib庫哦。否則就會報錯!還有個頭檔案。mmsystem.h。這個可加也可不加。有windows.h就可以了。
好啦!我們接收端的執行緒就完工了。程式完成一半了。先休息一下。呵呵。
Win32 SDK學習筆記3
1 思考一下,視窗程式中為什麼要註冊視窗類?你想建立什麼樣的視窗呢?那麼,建立什麼樣的視窗呢?建立前,window系統可不知道你要的是什麼型別的視窗啊 比如標題欄上顯示什麼圖示,滑鼠形狀是什麼,視窗背景顏色等等 這些型別資訊應在你建立前事先告訴window系統。可以採用這種方法 就是我們事先寫乙份要...
win32 sdk繪製矩形選擇框
普通的繪製會留下 痕跡 但windows程式設計第五版的5.3.8節提到了乙個繪圖模式的概念.具體內容就是我們可以通過呼叫setrop2函式對繪圖模式的設定,預設是r2 copypen,即畫筆畫素覆蓋背景畫素.注意這裡是對畫筆的繪圖模式進行設定,對畫刷沒用影響,所以只能老實的用線條畫矩形 setro...
VC串列埠通訊win32SDK版
vc串列埠通訊win32sdk版 2011年05月14日 win32串列埠程式設計 韓耀旭 在工業控制中,工控機 一般都基於windows平台 經常需要與智慧型儀表通過串列埠進行通訊。串列埠通訊方便易行,應用廣泛。一般情況下,工控機和各智慧型儀表通過rs485匯流排進行通訊。rs485的通訊方式是半...