




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 北京市昌平区新学道临川学校2026届高三化学第一学期期中考试模拟试题含解析
- 2025幼儿园食品安全突发事件应急处置方案
- 汽车行业供应链韧性构建与供应链物流优化报告2025
- 2025年网络文学出海战略解析:跨文化传播与全球市场布局报告
- 步长制药2023下半年ESG绩效报告:医药行业的ESG绩效与行业倡导
- 广州白云山制药2023上半年急救器械环境报告:守护生命共创绿色医疗
- 甘肃省白银市第九中学2026届化学高二上期中监测模拟试题含解析
- 薪酬合同(标准版)
- 无人机培训项目资金管理方案
- 供水管网改造期间的供水保障与服务
- 2025年GOLD COPD指南解读 课件
- 中国儿童肥胖诊断评估与管理专家共识解读 课件
- 老年人心理疏导与沟通培训
- SL631水利水电工程单元工程施工质量验收标准第3部分:地基处理与基础工程
- 2025时政试题及答案(100题)
- 数学分析1试题及答案
- 中职班主任培训学生管理
- 2025年上半年辽宁省沈阳市总工会“特邀审计专家”招聘3人重点基础提升(共500题)附带答案详解
- 《人工智能技术应用导论(第2版)》高职全套教学课件
- 供水设施智能化改造项目经济效益分析
- 《风光摄影技巧》课件
评论
0/150
提交评论