对做的一个小的C++聊天室的总结
這兩天照著教學視頻用C++做了個小的聊天室程序,只是實現接收端和發送端進行簡單的數據傳遞。主要分一下幾個步驟:
1、打開vc++建立一個MFC AppWizard(exe)的工程我的工程名為Caht緊接著選擇一個“基本對話框”將其里面的三個空間都刪去。添加一個組框并改其標題為”接受數據“,在組框中添加一個差不多大小的編輯框,改其ID為IDC_EDIT_RECV。接著在剛才那個組框下面在添加一個組框并將其標題改為”發送數據“再這個組框中添加一個IP地址空間和一個編輯框并將編輯框的ID改為”IDC_EDIT_SEND“。再在這個組框的下面添加一個按鈕修改其ID為”IDC_BTN_SEND“標題為”發送“。
2、這是一個基于SOCKET的程序,首先要在CChatApp的IniteInsastance文件中初始加載套接字代碼如下:BOOL CChatApp::InitInstance()
{
?if(!AfxSocketInit())
?{
???? AfxMessageBox("加載套接字庫失敗");
??return FALSE;
?}。。。。。
其中AfxSocketInit()函數返回一個布爾值。要想使用這個函數還需要在預編譯頭文件StdAfx中加入#include”Afxsock.h“
3、緊接著我們在CChatDlg中通過右鍵分別添加一個成員函數InitSocket和一個成員變量m_socket(設為private)在函數InitSocket()中添加如下代碼:BOOL CChatDlg::InitSocket()
{
??? 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(retval==SOCKET_ERROR)
?{
?? closesocket(m_socket);
?? MessageBox("綁定失敗");
?? return FALSE;
?}
?return TRUE;
}此段代碼用于綁定。并在OnInitDialog()中添加聲明InitSocket()。代碼如下:InitSocket();
4、接下來該接受數據啦,我們創建一個線程專門用來接受數據,并將接受到的數據顯示在編輯框中。我應該使用線程創建函數CreateThread()。線程的任務是接受到數據并將其顯示因此需要兩個參數,注意到CreateThread()函數的第四個參數為結構體指針,因此構造一個結構體,用此結構體傳遞這兩個參數。在CChatDlg()中添加一個結構體構造代碼如下:struct RECVPARAM
{
? SOCKET socket;
? HWND hwnd;
};最后這個雙引號注意不要丟掉。接著在OnInitDialog()聲明并引用這個結構體代碼如下:RECVPARAM *pRecvParam=new RECVPARAM;
?pRecvParam->socket=m_socket;
?pRecvParam->hwnd=m_hWnd;//m_hWnd是每個窗體對應的句柄。
接著在CreateThread()用這個結構體當參數。代碼如下:
HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
?CloseHandle(hThread);
?return TRUE;? // return TRUE? unless you set the focus to a control
}上面的這個函數CreateThread()的第三個參數是對應的是這個線程的功能函數RecvProc(要不將此函數聲明為靜態的要不將其在全局聲明)。在下面對此函數具體實現編碼如下:
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 說 %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
??????
?? ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
?}將接受過來的數據通過消息響應使其顯示到響應的編輯框中。編輯代碼步驟如下:
a:在CChatDlg中定義如下:#define WM_RECVDATA WM_USER+1
b:在下面相應的地方接著寫:afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);
c:在DoDataExchange(CDataExchange *pDx)中寫入如下代碼:
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);
}以上四部是一個消息的過程。
以上的接受端基本已經寫好了接下來該寫發送端啦。
5、雙擊發送按鈕自動生成一個void CChatDlg::OnBtnSend()函數其中的代碼如下:
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,"");
?
}
以上就是實現的整個過程。
我應該對如下的一些函數記住:socket()、bind()函數中具體參數的含義、句柄handle和hwnd具體含義、CreatThread()函數以及參數的具體含義還有其參數中的功能函數、sprintf()函數、afx_msg定義標識符的意義、recvfrom()函數及參數、inet_ntoa()函數功能:將網絡地址轉換成“.”點隔的字符串格式。postMessage()函數:、MV_USER所以自定義消息的步驟:(一)先在頭文件中定義自己消息的ID,如 #define WM_MY_FIRST_MESSAGE (WM_USER + 0x001) (二)再聲明自己的消息處理函數:afx_msg void OnMyFirstMessage(); (三)在CPP文件中添加消息映射宏: (四)最后定義消息處理函數:
總結
以上是生活随笔為你收集整理的对做的一个小的C++聊天室的总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于SSM的智慧房屋租赁系统
- 下一篇: SQLServer之事务简介