C++课程设计chat即时通讯工具开发_第1页
C++课程设计chat即时通讯工具开发_第2页
C++课程设计chat即时通讯工具开发_第3页
C++课程设计chat即时通讯工具开发_第4页
C++课程设计chat即时通讯工具开发_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

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

文档简介

面向对象C++课程设计题目:chat即时通讯工具开发院别:专业:信息与计算科学作者:学号:指导老师:日期:一、需求分析现今的局域网聊天软件大多功能复杂,操作繁琐,为了给局域网用户提供一个简单实用的聊天工具,我们开发了该软件。本软件主要实现了局域网的即时通讯和文件传输功能,所有的在局域网里面的人都可以互相聊天和传输文件。二、软件功能模块本软件的服务器管理图和客户端管理图如下2.1和2.2:即时通讯服务即时通讯服务接收客户端消息服务器管理接收客户连接请求接收客户端数据消息接收客户端退出消息验证登陆用户消息发出用户退出消息发给用户登陆消息消息修改用户信息删除用户增加用户转发用户即时消息图2.1服务器管理图客户端客户端服务发送系统消息客户端管理发送登陆消息发出退出登陆消息与服务器连接用户退出登陆传输数据用户登陆2.2客户端管理图三、关键技术实现客户端和服务端程序运行后图下图3.1,3.2,3.3,3.4和3.5图3.1登陆界面图3.2客户端界面图3.3服务器运行和修改界面图3.4客户端消息发送图3.5客户端文件发送客户端的关键代码: //连接服务器BOOLCClientDlg::Init(){ if(!m_bNetWorkInit) { sockaddr_indA; intslen=sizeof(sockaddr_in); memset(&dA,0,sizeof(dA)); dA.sin_family=AF_INET; unsignedlonginaddr; inaddr=inet_addr(m_strSvr); if(inaddr==INADDR_NONE) { hostent*host=NULL; host=gethostbyname(m_strSvr); if(host==NULL) { AfxMessageBox("找不到服务器,请确保服务器地址正确"); returnFALSE; } in_addrin; memcpy(&in,host->h_addr_list[0],host->h_length); chark[128]; strcpy(k,inet_ntoa(in)); inaddr=inet_addr(k); } if(inaddr!=INADDR_NONE) { memcpy(&dA.sin_addr,&inaddr,sizeof(inaddr)); } else { AfxMessageBox("inaddr!=INADDR_NONE"); returnFALSE; } dA.sin_port=htons(8188); m_sock=socket(AF_INET,SOCK_STREAM,0); if(INVALID_SOCKET==m_sock) { AfxMessageBox("socket创建套接字失败"); returnFALSE; } if(connect(m_sock,(sockaddr*)&dA,slen)<0) { AfxMessageBox("连接服务器失败,请确保服务器已启动服务器"); returnFALSE; } TDATA*pData=newTDATA; pData->hWnd=m_hWnd; pData->sock=m_sock; _beginthread(r,4026,(void*)pData); m_bNetWorkInit=TRUE; } returnTRUE;}//接收用户列表函数BOOLRecvUserList(HWNDhWnd,SOCKETsock){ //主窗口的句柄 CClientDlg*pDlg=(CClientDlg*)AfxGetMainWnd(); intnRecv=0; // intnSize=sizeof(Message)+sizeof(int); char*tmp=newchar[nSize]; //接受好友数量 nRecv=recv(sock,(char*)tmp,sizeof(int)*3,0); if(nRecv==0||nRecv==-1) { ::PostMessage(hWnd,WM_DISCONNECTED,NULL,sock); _endthread(); returnFALSE; } Messagemsg(tmp,sizeof(int)*3); delete[]tmp; intnLen=0; memcpy((char*)&nLen,msg.GetData(),sizeof(int)); //通知主窗口,有多少个好友 ::PostMessage(hWnd,WM_TOTAL_CONTACT,nLen,sock); //开始接收好友列表数据块 intnUsers=10; intnTimes=nLen/nUsers; intnRemind=nLen%nUsers; for(inti=0;i<(nTimes+1);i++) { intnCounter=0; intnRecvBufSize=0; intnRecvSize=0; char*buf=NULL; if(i==nTimes) { nRecvSize=nRemind*sizeof(UserInfo); } else { nRecvSize=nUsers*sizeof(UserInfo); } buf=newchar[nRecvSize]; ZeroMemory(buf,nRecvSize); while(nCounter<nRecvSize) { if(nCounter==0) nRecvBufSize=nRecvSize; else nRecvBufSize=nRecvSize-nCounter; nRecv=recv(sock,buf+nCounter,nRecvBufSize,0); if(nRecv==0||nRecv==-1) { AfxMessageBox("接收好友列表错误"); ::PostMessage(hWnd,WM_DISCONNECTED,(LPARAM)buf,sock); //自然死 _endthread(); returnFALSE; } nCounter+=nRecv; } char*nBuf=newchar[nCounter+sizeof(int)]; if(i==nTimes) { memcpy(nBuf,(char*)&nRemind,sizeof(int)); } else { memcpy(nBuf,(char*)&nUsers,sizeof(int)); } memcpy(nBuf+sizeof(int),buf,nCounter); delete[]buf; ::PostMessage(hWnd,WM_USERLIST,(WPARAM)nBuf,sock); } ::PostMessage(hWnd,WM_USERLISTEND,NULL,NULL); returnTRUE;}voidCClientDlg::r(void*p){ CClientDlg*pDlg=(CClientDlg*)AfxGetMainWnd(); if(NULL==p) _endthread(); TDATA*pData=(TDATA*)p; sockaddr_inaa; intslen=sizeof(aa); char*buf; intrval=0; getpeername(pData->sock,(sockaddr*)&aa,&slen); while(1) { intnBufSize=1024*2; buf=newchar[nBufSize]; //接收信息 rval=recv(pData->sock,buf,nBufSize,0); if(rval==0||rval==-1) { ::PostMessage(pData->hWnd,WM_DISCONNECTED,(LPARAM)buf,rval); deletepData; _endthread(); } Messagexmsg(buf,rval); deletebuf; HWNDhWnd=pData->hWnd; switch(xmsg.m_nMessage) { caseMSG_USEROK: { UserDetail*pDetail=newUserDetail; memcpy(pDetail,xmsg.GetData(),xmsg.GetDataLenght()); ::PostMessage(pData->hWnd,WM_USEROK,(LPARAM)pDetail,pData->sock); //接收用户列表信息 RecvUserList(pData->hWnd,pData->sock); } break; caseMSG_USERBAD: ::PostMessage(pData->hWnd,WM_USERBAD,0,pData->sock); break; caseMSG_USERINFO: { ::PostMessage(pData->hWnd,WM_USERINFO,0,pData->sock); } break; caseMSG_USERSTATUS: { char*buf=newchar[xmsg.GetDataLenght()]; memcpy(buf,xmsg.GetData(),xmsg.GetDataLenght()); ::PostMessage(pData->hWnd,WM_USERSTATUS,(WPARAM)buf,pData->sock); } break; caseMSG_NEWMESSAGE: { char*buf=newchar[xmsg.GetDataLenght()]; memcpy(buf,xmsg.GetData(),xmsg.GetDataLenght()); ::PostMessage(pData->hWnd,WM_MESSAGE,(WPARAM)buf,pData->sock); } break; //收到一个新的文件 caseMSG_FILE: { char*buf=newchar[xmsg.GetDataLenght()]; memcpy(buf,xmsg.GetData(),xmsg.GetDataLenght()); ::PostMessage(pData->hWnd,WM_FILE,(WPARAM)buf,pData->sock); } break; } } deletepData;}voidCClientDlg::OnUserOK(WPARAMwParam,LPARAMlParam){ UserDetail*pDetail=(UserDetail*)wParam; SetDlgItemText(IDC_EDIT_NICKNAME,pDetail->GetUNickName()); m_strUNickName=pDetail->GetUNickName(); SetDlgItemText(IDC_EDIT_USERNAME,pDetail->GetUID()); //向服务器请求用户列表 Messagexmsg; xmsg.m_nMessage=MSG_GETLIST; send(m_sock,xmsg.GetBuffer(),xmsg.GetBufferLength(),0); m_bLogedin=TRUE;}voidCClientDlg::OnUserBad(WPARAMwParam,LPARAMlParam){ if(IDYES==MessageBox("登录失败,用户名或密码错误!\n是否重新登陆?","错误",MB_YESNO)) { CLoginDlgdlg; if(IDOK==dlg.DoModal()) { } else { OnCancel(); return; } } else OnCancel();}voidCClientDlg::OnUserInfo(WPARAMwParam,LPARAMlParam){ char*buf=(char*)wParam; deletebuf;}voidCClientDlg::OnUserList(WPARAMwParam,LPARAMlParam){ DWORDdwCount; char*buf=(char*)wParam; memcpy((char*)&dwCount,buf,sizeof(DWORD)); intnIdx=sizeof(DWORD); CStringstr; UserInfoxui; HTREEITEMhItem; HTREEITEMhGroup; CStringstrGroupName; m_xtreeUser.SetRedraw(FALSE); for(inti=0;i<dwCount;i++) { //获取UserInfo数据 memcpy((char*)&xui,buf+nIdx,sizeof(UserInfo)); //把索引指向下一个数据块 nIdx+=sizeof(UserInfo); //获取组信息 map<string,HTREEITEM>::iteratoriGroup; iGroup=m_mapGroup.find(xui.GetUGroup()); if(iGroup==m_mapGroup.end()) //不存在 { hGroup=m_xtreeUser.InsertItem(xui.GetUGroup(),1,1); m_mapGroup.insert(pair<string,HTREEITEM>(xui.GetUGroup(),hGroup)); strGroupName=xui.GetUGroup(); } else { hGroup=iGroup->second; strGroupName=(iGroup->first).c_str(); } //把用户添加到联系人列表 if(xui.GetUStatus()==STATUS_ONLINE) //在线用户 { hItem=m_xtreeUser.InsertItem(xui.GetUNickName(),4,4,hGroup); m_xtreeUser.SetItemData(hItem,STATUS_ONLINE); m_xtreeUser.SetItemColor(hItem,RGB(25,79,149)); m_xtreeUser.UpdateGroupStatus(hGroup,strGroupName); m_dwOnLine++; } else//不在线用户 { hItem=m_xtreeUser.InsertItem(xui.GetUNickName(),3,3,hGroup); m_xtreeUser.SetItemData(hItem,STATUS_OFFLINE); m_xtreeUser.SetItemColor(hItem,RGB(128,128,128)); m_xtreeUser.UpdateGroupStatus(hGroup,strGroupName); } CChatDlg*pdlg=newCChatDlg; pdlg->m_strUser=xui.GetUNickName(); pdlg->m_strUID=xui.GetUID(); pdlg->m_bMobile=xui.UserHasMobile(); pdlg->m_sock=m_sock; m_mapUserList.insert(pair<HTREEITEM,CChatDlg*>(hItem,pdlg)); m_listUserInfo.push_back(xui); XSortUser(hGroup); } str.Format("联系人(%d/%d)",m_dwOnLine,m_mapUserList.size()); m_xtreeUser.SetRedraw(); SetDlgItemText(IDC_STATIC_CONTACT,str); //释放资源 delete[]buf;}服务器关键代码:voidCserverDlg::MsgOnLine(WPARAMwParam,LPARAMlParam){ //发件人的套接字 SOCKETsock=(SOCKET)lParam; LPPER_IO_OPERATION_DATAPerIoData=(LPPER_IO_OPERATION_DATA)wParam; DWORDSendBytes; MESSAGExmsg; char*buf=(char*)PerIoData->DataBuf.buf; MSG_ONLINEomsg(buf); map<SOCKET,UserInfo>::iteratorimap; //收件人的套接字 for(imap=m_mapUserInfos.begin();imap!=m_mapUserInfos.end();++imap) { if(!strcmp(imap->second.GetUID(),omsg.GetUID())) { //发件人 //收件人 //信息内容 omsg.SetUID(m_mapUserInfos[sock].GetUID()); xmsg.m_nMessage=MSG_NEWMESSAGE; xmsg.SetData(omsg.GetBuffer(),omsg.GetBufferLength()); LPPER_IO_OPERATION_DATApIo=(LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA)); ZeroMemory(&(pIo->Overlapped),sizeof(OVERLAPPED)); memcpy(pIo->Buffer,xmsg.GetBuffer(),xmsg.GetBufferLength()); pIo->DataBuf.buf=pIo->Buffer; pIo->DataBuf.len=xmsg.GetBufferLength(); pIo->DataSize=xmsg.GetBufferLength(); pIo->send=1; if(SOCKET_ERROR==WSASend(imap->first,&(pIo->DataBuf),1,&SendBytes,0,&(pIo->Overlapped),NULL)) { if(WSAGetLastError()!=ERROR_IO_PENDING) { AfxMessageBox("WSASenderror"); return; } } break; } } //恢复SOCKET的状态 ResetSockState(sock,PerIoData); deletebuf;}voidCserverDlg::Logoff(WPARAMwParam,LPARAMlParam){ SOCKETsIndex=(SOCKET)lParam; map<SOCKET,UserInfo>::iteratoriUserInfo; iUserInfo=m_mapUserInfos.find(sIndex); if(iUserInfo==m_mapUserInfos.end()) { return; } //用户退出,对数据库进行标识 DBUserLogout(m_mapUserInfos[sIndex].GetUID()); CStringstrText=m_mapUserInfos[sIndex].GetUNickName(); m_mapUserInfos[sIndex].OffLine(); if(!m_bSendUserStatus) { m_bSendUserStatus=TRUE; SetTimer(TIMER_SEND_STATUS,TIMER_SEND_STATUS_TIME,NULL); } m_listUserStatus.push_back(m_mapUserInfos[sIndex]); //显示状态为离线 intnItemCount=m_lcUserList.GetItemCount(); for(inti=0;i<nItemCount;i++) { charbuf[32]; m_lcUserList.GetItemText(i,1,buf,32); if(!strcmp(buf,m_mapUserInfos[sIndex].GetUID())) { m_lcUserList.SetItemText(i,3,"离线"); m_lcUserList.SetItemState(i,~LVIS_SELECTED,LVIS_SELECTED); m_lcUserList.SetItemState(i,LVIS_SELECTED,LVIS_SELECTED); m_lcUserList.SetItemState(i,~LVIS_SELECTED,LVIS_SELECTED); break; } } list<UserDetail>::iteratoriDetail; for(iDetail=m_listUserDetail.begin();iDetail!=m_listUserDetail.end();++iDetail) { UserInfouinfo; iDetail->GetUserInfo(uinfo); if(m_mapUserInfos[sIndex]==uinfo) { iDetail->OffLine(); } }}//用户请求用户列表voidCserverDlg::GetList(WPARAMwParam,LPARAMlParam){ SOCKETsock=(SOCKET)lParam; LPPER_IO_OPERATION_DATAPerIoData=(LPPER_IO_OPERATION_DATA)wParam; //恢复SOCKET的状态 ResetSockState(sock,PerIoData); m_listContactQuery.push_back(sock); if(!m_bSendUserContact) { SetTimer(TIMER_SEND_CONTACT,TIMER_SEND_CONTACT_TIME,NULL); m_bSendUserContact=TRUE; }}//用户上线消息发给好友voidCserverDlg::SendUserStatusToFriends(UserInfo&uinfo){ //TODO:Addyourcontrolnotificationhandlercodehere list<string>list_contact; //SQL查询语句 char*szSQL="SELECT*FROMx_contactwhereuid='%s'"; CStringstrSQL; strSQL.Format(szSQL,uinfo.GetUID()); //ADO操作模块 _RecordsetPtrpRs; pRs.CreateInstance(__uuidof(Recordset)); //执行相应处理 try { pRs->Open((LPCTSTR)strSQL, m_pConn.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText); //如果数据库是空白的 if(!pRs->adoEOF) { //读取并显示数据库里的信息 while(!pRs->adoEOF) { variant_tvar; //获取用户昵称 var=pRs->GetCollect(_variant_t("xucontact")); if(var.vt!=VT_NULL) { list_contact.push_back((LPCTSTR)_bstr_t(var)); } pRs->MoveNext(); } } } catch(_com_errore) { AfxMessageBox("把上线消息发给好友时有错误"); } //释放ADO对象 pRs->Close(); pRs.Release(); list<string>::iteratoriContact; DWORDSendBytes; map<SOCKET,UserInfo>::iteratoriUserInfo; for(iUserInfo=m_mapUserInfos.begin();iUserInfo!=m_mapUserInfos.end();++iUserInfo) { //用户处于离线状态就略过 if(iUserInfo->second.GetUStatus()==STATUS_OFFLINE) continue; stringstrUID=iUserInfo->second.GetUID(); iContact=find(list_contact.begin(),list_contact.end(),strUID); if(iContact!=list_contact.end()) { LPPER_IO_OPERATION_DATAPe

温馨提示

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

最新文档

评论

0/150

提交评论