对做的一个小的C++聊天室的总结
這兩天照著教學(xué)視頻用C++做了個(gè)小的聊天室程序,只是實(shí)現(xiàn)接收端和發(fā)送端進(jìn)行簡(jiǎn)單的數(shù)據(jù)傳遞。主要分一下幾個(gè)步驟:
1、打開(kāi)vc++建立一個(gè)MFC AppWizard(exe)的工程我的工程名為Caht緊接著選擇一個(gè)“基本對(duì)話(huà)框”將其里面的三個(gè)空間都刪去。添加一個(gè)組框并改其標(biāo)題為”接受數(shù)據(jù)“,在組框中添加一個(gè)差不多大小的編輯框,改其ID為IDC_EDIT_RECV。接著在剛才那個(gè)組框下面在添加一個(gè)組框并將其標(biāo)題改為”發(fā)送數(shù)據(jù)“再這個(gè)組框中添加一個(gè)IP地址空間和一個(gè)編輯框并將編輯框的ID改為”IDC_EDIT_SEND“。再在這個(gè)組框的下面添加一個(gè)按鈕修改其ID為”IDC_BTN_SEND“標(biāo)題為”發(fā)送“。
2、這是一個(gè)基于SOCKET的程序,首先要在CChatApp的IniteInsastance文件中初始加載套接字代碼如下:BOOL CChatApp::InitInstance()
{
?if(!AfxSocketInit())
?{
???? AfxMessageBox("加載套接字庫(kù)失敗");
??return FALSE;
?}。。。。。
其中AfxSocketInit()函數(shù)返回一個(gè)布爾值。要想使用這個(gè)函數(shù)還需要在預(yù)編譯頭文件StdAfx中加入#include”Afxsock.h“
3、緊接著我們?cè)贑ChatDlg中通過(guò)右鍵分別添加一個(gè)成員函數(shù)InitSocket和一個(gè)成員變量m_socket(設(shè)為private)在函數(shù)InitSocket()中添加如下代碼:BOOL CChatDlg::InitSocket()
{
??? m_socket=socket(AF_INET,SOCK_DGRAM,0);
?if(INVALID_SOCKET==m_socket)
?{
???? MessageBox("套接字創(chuàng)建失敗");
??return FALSE;
?} 此段代碼用于創(chuàng)建初始化套接字。緊接著寫(xiě)如下代碼:
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(retval==SOCKET_ERROR)
?{
?? closesocket(m_socket);
?? MessageBox("綁定失敗");
?? return FALSE;
?}
?return TRUE;
}此段代碼用于綁定。并在OnInitDialog()中添加聲明InitSocket()。代碼如下:InitSocket();
4、接下來(lái)該接受數(shù)據(jù)啦,我們創(chuàng)建一個(gè)線(xiàn)程專(zhuān)門(mén)用來(lái)接受數(shù)據(jù),并將接受到的數(shù)據(jù)顯示在編輯框中。我應(yīng)該使用線(xiàn)程創(chuàng)建函數(shù)CreateThread()。線(xiàn)程的任務(wù)是接受到數(shù)據(jù)并將其顯示因此需要兩個(gè)參數(shù),注意到CreateThread()函數(shù)的第四個(gè)參數(shù)為結(jié)構(gòu)體指針,因此構(gòu)造一個(gè)結(jié)構(gòu)體,用此結(jié)構(gòu)體傳遞這兩個(gè)參數(shù)。在CChatDlg()中添加一個(gè)結(jié)構(gòu)體構(gòu)造代碼如下:struct RECVPARAM
{
? SOCKET socket;
? HWND hwnd;
};最后這個(gè)雙引號(hào)注意不要丟掉。接著在OnInitDialog()聲明并引用這個(gè)結(jié)構(gòu)體代碼如下:RECVPARAM *pRecvParam=new RECVPARAM;
?pRecvParam->socket=m_socket;
?pRecvParam->hwnd=m_hWnd;//m_hWnd是每個(gè)窗體對(duì)應(yīng)的句柄。
接著在CreateThread()用這個(gè)結(jié)構(gòu)體當(dāng)參數(shù)。代碼如下:
HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
?CloseHandle(hThread);
?return TRUE;? // return TRUE? unless you set the focus to a control
}上面的這個(gè)函數(shù)CreateThread()的第三個(gè)參數(shù)是對(duì)應(yīng)的是這個(gè)線(xiàn)程的功能函數(shù)RecvProc(要不將此函數(shù)聲明為靜態(tài)的要不將其在全局聲明)。在下面對(duì)此函數(shù)具體實(shí)現(xiàn)編碼如下:
DWORD WINAPI CChatDlg::RecvProc(LPVOID IpParameter)
{
?SOCKET socket=((RECVPARAM*)IpParameter)->socket;
?HWND hwnd=((RECVPARAM*)IpParameter)->hwnd;
?SOCKADDR_IN addrFrom;
?int len=sizeof(SOCKADDR);
?char recvBuf[200];
?char tempBuf[300];
?int retval;
?while(TRUE)
?{
?? retval=recvfrom(socket,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
?? if(SOCKET_ERROR==retval)
??? break;
?? sprintf(tempBuf,"%s 說(shuō) %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
??????
?? ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
?}將接受過(guò)來(lái)的數(shù)據(jù)通過(guò)消息響應(yīng)使其顯示到響應(yīng)的編輯框中。編輯代碼步驟如下:
a:在CChatDlg中定義如下:#define WM_RECVDATA WM_USER+1
b:在下面相應(yīng)的地方接著寫(xiě):afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);
c:在DoDataExchange(CDataExchange *pDx)中寫(xiě)入如下代碼:
BEGIN_MESSAGE_MAP(CChatDlg, CDialog)
?//{{AFX_MSG_MAP(CChatDlg)
?ON_WM_SYSCOMMAND()
?ON_WM_PAINT()
?ON_WM_QUERYDRAGICON()
?ON_BN_CLICKED(IDC_BTN_SEND, OnBtnSend)
?//}}AFX_MSG_MAP
ON_MESSAGE(WM_RECVDATA,OnRecvData)
END_MESSAGE_MAP()
d:
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);
}以上四部是一個(gè)消息的過(guò)程。
以上的接受端基本已經(jīng)寫(xiě)好了接下來(lái)該寫(xiě)發(fā)送端啦。
5、雙擊發(fā)送按鈕自動(dòng)生成一個(gè)void CChatDlg::OnBtnSend()函數(shù)其中的代碼如下:
void CChatDlg::OnBtnSend()
{
?// TODO: Add your control notification handler code here
?DWORD dvIp;
?((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dvIp);
?SOCKADDR_IN AddrTo;
?AddrTo.sin_family=AF_INET;
?AddrTo.sin_port=htons(6000);
?AddrTo.sin_addr.S_un.S_addr=htonl(dvIp);
?CString strSend;
?GetDlgItemText(IDC_EDIT_SEND,strSend);
?sendto(m_socket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&AddrTo,sizeof(SOCKADDR));
?SetDlgItemText(IDC_EDIT_SEND,"");
?
}
以上就是實(shí)現(xiàn)的整個(gè)過(guò)程。
我應(yīng)該對(duì)如下的一些函數(shù)記住:socket()、bind()函數(shù)中具體參數(shù)的含義、句柄handle和hwnd具體含義、CreatThread()函數(shù)以及參數(shù)的具體含義還有其參數(shù)中的功能函數(shù)、sprintf()函數(shù)、afx_msg定義標(biāo)識(shí)符的意義、recvfrom()函數(shù)及參數(shù)、inet_ntoa()函數(shù)功能:將網(wǎng)絡(luò)地址轉(zhuǎn)換成“.”點(diǎn)隔的字符串格式。postMessage()函數(shù):、MV_USER所以自定義消息的步驟:(一)先在頭文件中定義自己消息的ID,如 #define WM_MY_FIRST_MESSAGE (WM_USER + 0x001) (二)再聲明自己的消息處理函數(shù):afx_msg void OnMyFirstMessage(); (三)在CPP文件中添加消息映射宏: (四)最后定義消息處理函數(shù):
總結(jié)
以上是生活随笔為你收集整理的对做的一个小的C++聊天室的总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 基于SSM的智慧房屋租赁系统
- 下一篇: C++搭建集群聊天室(二):安装mudu