C++课程设计:聊天室_第1页
C++课程设计:聊天室_第2页
C++课程设计:聊天室_第3页
C++课程设计:聊天室_第4页
C++课程设计:聊天室_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.课 程 设 计 报 告课程名称:面向对象程序设计C+设计题目: 聊天室_专 业:计算机科学与技术_姓 名: _学 号: 指导教师:李 晓 虹_2015 年 12 月 20 日一 系统需求分析这次开发的局域网聊天工具目标在于在局域网环境下能够简单的实现人与人的即时通讯,要求收发信息速度快、安全性高和精准性高。本软件基于visual studio 2010环境下开发,并采用MFC进行处理,界面具有基本的功能按钮。同时,本软件包含有客户端和服务端,他们之间是基于UDP协议下进行通信的。1.1设计要求:采用C/S模式,分为客户端与服务器端程序1.2功能要求:1.21服务器端(1) 服务器聊天程序要在

2、待定的端口上等待来自聊天客户的连接请求,并且需要维护一个客户连接表,以记录所有成功的连接。(2) 服务器聊天程序要及时接受从各个聊天客户发送过来的信息,然后把这些信息转发到一个或多个客户连接。对于公共聊天室,服务器将把接受到的信息向除源端外的所有客户发送过去。(3) 服务器还要监控这些连接的状态,在客户主动离开或发生故障时从列表中删除相应的表项,并及时更新连接表。1.21客户端(1) 客户端聊天程序要负责建立和维护与服务器的连接,通过获取用户的设置尝试与服务器的连接,并且随时检测连接的状态。(2) 客户端聊天程序要把用户输入的信息及时发送到聊天服务器。一般情况下,当用户输入一行信息并且按下回车

3、键后聊天程序就要把这一行信息发送出去,才能及时地满足用户的交互需求。(3) 要随时准备好接受来自服务器的信息,随时把接受到的信息显示出来,让用户及时看到对方的响应。(4) 在用户退出聊天过程是要关闭与服务器的连接。二 总体设计支持多个客户端的连接,在服务器和多个客户端之间进行数据传输; 接收客户端发送的消息,并显示在一个列表框中; 在用户连接上后有提示,显示出连接的用户名字; 发送信息时可以显示聊天的所有记录.服务器连接套接头侦听套接字客户机 Socket()Socket()Bind()Bind()Listen()Connect()创建连接套接口Accept()S

4、end()Receive()Receive()Receive()CloseSocket()CloseSocket()CloseSocket()三 详细设计3.1数据库代码和表:create table imuser (ImNo char(15) primary key, ImName char(15), ImPhone char(15), ImIp char(15), ImPassword char(15), ImOnline int, ImPort char(10) create table friend (ImNo1 char(15), ImNo2 char(15), primary ke

5、y (ImNo1,ImNo2), foreign key(ImNo1) references imuser(Imno), foreign key(ImNo2) references imuser(Imno)create table OfflineMessage (ImNo char(15), ImMsg binary(1536) create table OffAddfriend (ImNo char(15), ImInfo binary(500) 表3-1用户表结构表3-2离线用户表结构表3-3请求加为好友用户表结构表3-4用户信息表3.2 C+各模块代码实现:1)始化套接字BOOL CCH

6、ATDlg:InitSocket() m_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); if(m_socket=INVALID_SOCKET) MessageBox("套接字创建失败!"); return FALSE; SOCKADDR_IN ServerAddr; ServerAddr.sin_family=AF_INET; ServerAddr.sin_port= htons(6000); ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);int retval; ret

7、val=bind(m_socket,(SOCKADDR*)&ServerAddr,sizeof(SOCKADDR); if(retval=SOCKET_ERROR) closesocket(m_socket); MessageBox("绑定失败!"); return FALSE; return TRUE; 2)、/消息处理函数,注意在声明时应该为staticDWORD WINAPI CCHATDlg:RecvProc(LPVOID lpParameter) SOCKET sock=(RECVPARAM*)lpParameter)->sock; HWND hwn

8、d=(RECVPARAM*)lpParameter)->hwnd; SOCKADDR_IN ClientAddr; int len=sizeof(SOCKADDR); char recvBuf512; char tempBuf512; int retval;while(1) retval=recvfrom(sock,recvBuf,512,0,(SOCKADDR*)&ClientAddr,&len); if(retval=SOCKET_ERROR) break; sprintf(tempBuf,"(%s): %s",inet_ntoa(ClientAd

9、dr.sin_addr),recvBuf); :PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf); return 0; 3)、同时,在BOOL CCHATDlg:OnInitDialog()添加如下代码:InitSocket(); /套接字初始化 RECVPARAM *pRecvParam=new RECVPARAM; pRecvParam->sock=m_socket; pRecvParam->hwnd=m_hWnd; HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvP

10、aram,0,NULL);CloseHandle(hThread);定义一个全局静态变量CString NewString 用于进行格式输出和记录聊天消息4)发送数据void CCHATDlg:OnBtnSend() /TODO: Add your control notification handler code her DWORD dwIP; (CIPAddressCtrl*)GetDlgIt SOCKADDR_IN ClientAddr; ClientAddr.sin_family=AF_INET; ClientAddr.sin_port= htons(5150); ClientAddr

11、.sin_addr.S_un.S_addr = htonl(dwIP); CString strSend; CString strTime; GetDlgItemText(IDC_EDIT_SEND,strSend); if(strSend.GetLength()=0) MessageBox("发送的消息不能为空!"); else sendto(m_socket,strSend,strSend.GetLength() 1,0,(SOCKADDR*)&ClientAddr,sizeof(SOCKADDR); SetDlgItemText(IDC_EDIT_SEND,&

12、quot;"); /聊天消息时间记录 CTime tm; tm=CTime:GetCurrentTime(); strTime=tm.Format("%Y-%m-%d %X"); strSend=strSend " 【" strSend =strTime; strSend=strSend "】" strSend ="" NewString ="" NewString ="我: " NewString =strSend; Record(NewString); /调用消

13、息记录函数 SetDlgItemText(IDC_EDIT_RECV,NewString); /回显在本地聊天窗口 5)、/接收数据void CCHATDlg:OnRecvData(WPARAM wParam,LPARAM lParam) CString str=(char*)lParam; CString strTime GetDlgItemText(IDC_EDIT_RECV,NewString); /聊天消息时间记录 CTime tm; tm=CTime:GetCurrentTime();strTime=tm.Format("%Y-%m-%d %X"); str=st

14、r " 【" str =strTime; str=str "】" str ="" NewString ="" NewString =str; SetDlgItemText(IDC_EDIT_RECV,NewString); Record(NewString); /调用消息记录函数 6)、附加查询本地主机名和IP功能 void CCHATDlg:OnBUTTONsearch() /查询按钮 WSADATA wsaData; WSAStartup(MAKEWORD(1,1),&wsaData); char sz

15、HostName128; if(gethostname(szHostName,128)=0) /获取主机名 m_HostName.SetWindowText(szHostName); hostent* ent=gethostbyname(szHostName); /获取主机信息 for(int i=0;ent!=NULL && ent->h_addr_listi!=NULL;i ) LPCTSTR IpAddr=inet_ntoa(*(in_addr*)ent->h_addr_listi); 分十进制格式 m_IPAddr.AddString(IpAddr); WS

16、ACleanup(); /转换成点7)、聊天记录int CCHATDlg:Record(CString recordString) /消息记录函数 CFile recordFile("TheRec /定义文件对象 recordFile.Write(recordString,strlen(recordString); recordFile.Close(); return 0; 8)、在CHATDlg.h文件添加宏:#define WM_RECVDATA WM_USER 19)、请求登录、退出等部分功能代码BOOL CP2PServer:SendText(const MessageInf

17、o& info,CString szText,PEER_INFO& peer)int nTextLen=szText.GetLength()+1;if(nTextLen > 1024-sizeof(CP2PMessage)-sizeof(MessageInfo)AfxMessageBox("发送失败,可能是发送的数据太长");return FALSE;switch(pMsg->nMessageType) case USERLOGIN: strNo=pMsg->peer.ImNo;strPassword=(char*)(pMsg+1);tim

18、e=COleDateTime:GetCurrentTime();strTime=time.Format("%H:%M:%S ");strLog=strTime+strNo+" 请求登陆":PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0); vSQL="select * from imuser where ImNo='"+strNo+"' and Impassword='"+strPassword+&quo

19、t;' and ImOnline=0"m_record=pThis->ado.GetRecordSet(vSQL);if(!m_record->adoEOF) time=COleDateTime:GetCurrentTime();strTime=time.Format("%H:%M:%S ");strLog=strTime+strNo+" 登陆成功":PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);break;case USERLOGO

20、UT:strNo=pMsg->peer.ImNo;strName=pMsg->peer.ImName;time=COleDateTime:GetCurrentTime();strTime=time.Format("%H:%M:%S ");strLog=strTime+strNo+" 退出":PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);elsetime=COleDateTime:GetCurrentTime();strTime=time.Format(

21、"%H:%M:%S ");strLog=strTime+strFrom+"->"+strNo+" 语音请求":sendto(pThis->g_s,(char*)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr);else if(pMsg->nMessageType=GETVOIP)pMsg->nMessageType=GETVOIPACK;pMsg->peer.p2pAddr.nPort=10000; :send

22、to(pThis->g_s,(char *)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr); break;case ADDFRIEND: CString strFrom,strTo;strFrom=pMsg->peer.ImNo;strTo=(char *)(pMsg+1); time=COleDateTime:GetCurrentTime();strTime=time.Format("%H:%M:%S ");strLog=strTime+strFrom+"

23、;->"+strTo+" 加为好友":PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0);strNo=(char*)(pMsg+1);vSQL="select * from imuser where ImNo='"+strTo+"' "m_record=pThis->ado.GetRecordSet(vSQL);if(!m_record->adoEOF) strIp=(LPCTSTR)(_bstr_t)m_

24、record->GetCollect("ImIp");strPort=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImPort");strOnline=(LPCTSTR)(_bstr_t)m_record->GetCollect("ImOnline");strIp.TrimRight(" ");strPort.TrimRight(" ");strOnline.TrimRight(" ");if(strOnline=&quo

25、t;1" && strPort!="0")remoteAddr.sin_addr.S_un.S_addr=inet_addr(strIp);remoteAddr.sin_port=htons(atoi(strPort);:sendto(pThis->g_s,(char*)pMsg,sizeof(CP2PMessage)+sizeof(NewFriendMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr); case ADDFRIENDACK: CString strFrom,strT

26、o; BOOL bAllow; NewFriendMessage *pNew=(NewFriendMessage *)(pMsg+1); strFrom=pNew->szNo; strTo=pMsg->peer.ImNo; bAllow=pNew->bAllow;time=COleDateTime:GetCurrentTime();strTime=time.Format("%H:%M:%S ");strLog=strTime+strTo+"->"+strFrom+" 接受加为好友"/AfxMessageBox(

27、"对不起,对方正在通话中,请稍后再拨!");else g_strVOIP=:inet_ntoa(remoteAddr.sin_addr);g_nVOIPPort=pMsg->peer.p2pAddr.nPort;break;case OFFP2PMESSAGE:DWORD size=dwRecv-sizeof(CP2PMessage)-sizeof(MessageInfo)-MAX_USERNAME; MessageInfo *pInfo=(MessageInfo *)(pMsg+1);char *pNo=(char *)(pInfo+1);CString strFr

28、om,strTo;strFrom=pMsg->peer.ImNo;strTo=pNo;time=COleDateTime:GetCurrentTime();strTime=time.Format("%H:%M:%S ");strLog=strTime+strFrom+"->"+strTo+" 离线消息":PostMessage(g_pPage3->m_hWnd,WM_NEWLOG,(WPARAM)(LPCTSTR)strLog,0); vSQL="select * from OfflineMessage&q

29、uot; m_record=pThis->ado.GetRecordSet(vSQL);m_record->AddNew(); m_record->PutCollect("ImNo",_variant_t(pNo); memcpy(pNo,pNo+MAX_USERNAME,size); char*pBuf = buff; VARIANTvarBLOB; SAFEARRAY*psa; SAFEARRAYBOUNDrgsabound1; if(pBuf) size=dwRecv-MAX_USERNAME; rgsabound0.lLbound = 0; rgsabound0.cElements = size; psa = SafeArrayCreate(VT_UI1, 1, rgsabou

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论