老師的作業,讓做一個區域網路聊天室!看了孫鑫的視頻!自己也簡單的實現了一下!感覺挺棒的!
一個中心-----"練習"
下面貼出自己的簡單理解,告訴自動掠過,,,,,,,,,
聊天室基於UDP協議,
1.通訊端初始化
AfxSocketInit()函數初始化
1 if(!AfxSocketInit())
2 {
3 AfxMessageBox("載入通訊端失敗庫!");
4 return FALSE;
5 }
通訊端初始化完成,當然我們得在先行編譯標頭檔裡面將AfxSocketInit()所需的標頭檔包含進來,否則他不認識的!
1 #include <afxsock.h> //stdfax.h中的
BOOL CNetworkDlg::InintScoket(){m_scoket=socket(AF_INET,SOCK_DGRAM,0); //自己要做的工作-----定義私人變數成員if(INVALID_SOCKET==m_scoket){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 reval;reval=bind(m_scoket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));if(SOCKET_ERROR==reval){closesocket(m_scoket);MessageBox("綁定失敗!");return FALSE;}return TRUE;}
這樣我們就可以在OnInitDialog()裡面調用了;
2.接收端
接收端由於要處理即時訊息,所以單獨做出一個線程來處理!我們來看一下MSDN的解釋:
CreateThreadThe CreateThread function creates a thread to execute within the virtual address space of the calling process. To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function. HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD DWORD dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId // thread identifier);
以上函數,各個參數我就這裡不解釋了(具體我其實不知道看孫鑫十五課)第三個參數是我們關注的對象!只能傳進去一個參數!然而我們想處理的卻有兩個:通訊端和視窗控制代碼!
我們注意到這是一個指標!所以我們做一個結構體將其作為指標傳進得到兩個值
1 struct RECEPARAM
2 {
3 SOCKET socket;
4 HWND hwnd;
5 };
然後放到OnInitDialog()調用CreateThread()得到其控制代碼
1 RECEPARAM *pReceParam=new RECEPARAM;
2 pReceParam->socket=m_scoket;
3 pReceParam->hwnd=m_hWnd;
4 HANDLE hThread=CreateThread(NULL,0,ReceProc,(LPVOID)pReceParam,0,NULL); //注意到Rece是線程建立的函數!
5 CloseHandle(hThread);
下面寫先從建立函數!ReceProc();
1 DWORD WINAPI CNetworkDlg::ReceProc(LPVOID lpParameter)
2 {
3 SOCKET sock=((RECEPARAM*)lpParameter)->socket;
4 HWND hwnd=((RECEPARAM*)lpParameter)->hwnd;
5
6 //接收資料
7 SOCKADDR_IN addr_form;
8 int len=sizeof(SOCKADDR);
9 char recBuf[200];
10 char tempBuf[300];
11
12 int retval;
13 while(TRUE)
14 {
15 retval=recvfrom(sock,recBuf,200,0,(SOCKADDR*)&addr_form,&len);
16 if ( SOCKET_ERROR ==retval)
17 {
18 break;
19 }
20 sprintf(tempBuf,"%s 說: %s",inet_ntoa(addr_form.sin_addr),recBuf);
21 ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
22 }
23
24
25 return 0;
26 }
整個程式運行起來,線程就不斷的跑了(while(true))!
當來訊息時,怎麼辦呢?
下面是訊息處理函數:
1 afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam); //聲明為私人函數
1 void CNetworkDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
2 {
3
4 CString str=(char*)lParam;
5 CString strTemp;
6 GetDlgItemText(IDC_EDIT_RECE,strTemp);
7 str+="\r\n";
8 str+=strTemp;
9 SetDlgItemText(IDC_EDIT_RECE,str);
10 }
這樣就能處理了.......
下面類看一下介面吧(開始就該設計好的)
當要點擊發送時要完成的工作:擷取IP,儲存並傳入內容,送過去讓線程捕獲!
雙擊介面“發送”
1 void CNetworkDlg::OnBtnSend()
2 {
3 // TODO: Add your control notification handler code here
4 DWORD dwip;
5
6 ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS2))->GetAddress(dwip);
7 SOCKADDR_IN addrTo;
8 addrTo.sin_family=AF_INET;
9 addrTo.sin_port=htons(6000);
10 addrTo.sin_addr.S_un.S_addr=htonl(dwip) ;
11
12 CString strSend;
13 GetDlgItemText(IDC_EDIT2,strSend);
14 sendto(m_scoket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));
15 SetDlgItemText(IDC_EDIT2,"");
16
17 }
好了,發送過去了,正在跑動的線程一捕獲,立馬顯示給編輯框!
我實驗了一下,有個bug,看不到自己的發送內容(明明儲存了內容怎麼就消失了呢?)
自己給自己發可以,兩台電腦上有問題!摸索中,,,,,,,,