chatserverdoc.cpp
来自「基于winsock的聊天程序」· C++ 代码 · 共 549 行
CPP
549 行
// ChatServerDoc.cpp : implementation of the CChatServerDoc class
//
#include "stdafx.h"
#include "ChatServer.h"
#include "ChatServerDoc.h"
#include "CntrItem.h"
#include "Msg.h"
#include "ChatServerView.h"
#include "logindlg.h"
#include "mainfrm.h"
#include "CleanDlg.h"
#include "brandCast.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc
IMPLEMENT_DYNCREATE(CChatServerDoc, CRichEditDoc)
BEGIN_MESSAGE_MAP(CChatServerDoc, CRichEditDoc)
//{{AFX_MSG_MAP(CChatServerDoc)
ON_COMMAND(ID_SERVER_BRANDCAST, OnServerBrandcast)
//}}AFX_MSG_MAP
// Enable default OLE container implementation
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, CRichEditDoc::OnUpdateEditLinksMenu)
ON_COMMAND(ID_OLE_EDIT_LINKS, CRichEditDoc::OnEditLinks)
ON_UPDATE_COMMAND_UI_RANGE(ID_OLE_VERB_FIRST, ID_OLE_VERB_LAST, CRichEditDoc::OnUpdateObjectVerbMenu)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc construction/destruction
CChatServerDoc::CChatServerDoc()
{
// TODO: add one-time construction code here
m_pSocket = NULL;
m_lCount = 0;
}
CChatServerDoc::~CChatServerDoc()
{
if(m_pSocket != NULL)
delete m_pSocket;
m_pSocket = NULL;
}
BOOL CChatServerDoc::OnNewDocument()
{
if (!CRichEditDoc::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
//Create server
CLoginDlg dlg;
while(TRUE)
{
if(dlg.DoModal()!=IDOK)
{
return FALSE;
}
m_pSocket = new CListeningSocket(this);
if (m_pSocket->Create(dlg.m_nPort,SOCK_STREAM,dlg.m_strAddress))
{
if (m_pSocket->Listen())
{
SetTitle("聊天工具服务器端");
return TRUE;
}
}
}
return TRUE;
}
CRichEditCntrItem* CChatServerDoc::CreateClientItem(REOBJECT* preo) const
{
// cast away constness of this
return new CChatServerCntrItem(preo, (CChatServerDoc*) this);
}
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc serialization
void CChatServerDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
// Calling the base class CRichEditDoc enables serialization
// of the container document's COleClientItem objects.
// TODO: set CRichEditDoc::m_bRTF = FALSE if you are serializing as text
CRichEditDoc::Serialize(ar);
}
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc diagnostics
#ifdef _DEBUG
void CChatServerDoc::AssertValid() const
{
CRichEditDoc::AssertValid();
}
void CChatServerDoc::Dump(CDumpContext& dc) const
{
CRichEditDoc::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc commands
void CChatServerDoc::DeleteContents()
{
//Before Server Exit,Send Exit-Message to all user!
delete m_pSocket;
m_pSocket = NULL;
CString temp;
temp="服务器已经关掉!";
CMsg* pMsg = new CMsg;
while(!m_connectionList.IsEmpty())
{
CClientSocket* pSocket = (CClientSocket*)m_connectionList.RemoveHead();
if(pSocket==NULL ) continue;
if (pMsg == NULL) continue;
pMsg->m_bClose = TRUE;
pMsg->m_strFrom = pSocket->name;
pMsg->m_strText = _TEXT("服务器已关闭");
pMsg->m_strTo = _TEXT("所有人");
pMsg->m_nType = -3;
SendMsg(pSocket, pMsg);
if(!pSocket->IsAborted())
{
pSocket->ShutDown();
BYTE Buffer[50];
while (pSocket->Receive(Buffer,50) > 0);
delete pSocket;
}
}
delete pMsg;
if (!m_viewList.IsEmpty())
((CRichEditView*)m_viewList.GetHead())->SetWindowText(_T(""));
CDocument::DeleteContents();
}
void CChatServerDoc::UpdateClients()
{
//Update Message
CMsg* pMsg = AssembleMsg(NULL);
if(pMsg->m_nType>= 0)
m_lCount ++;
for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos);
if (pMsg != NULL)
SendMsg(pSocket, pMsg);
}
}
void CChatServerDoc::ProcessPendingAccept()
{
//Accept new user
CClientSocket* pSocket = new CClientSocket(this);
if (m_pSocket->Accept(*pSocket))
{
pSocket->Init();
m_connectionList.AddTail(pSocket);
}
else
delete pSocket;
}
void CChatServerDoc::ProcessPendingRead(CClientSocket* pSocket)
{
//Read message
if(pSocket != NULL)
{
do{
CMsg* pMsg = ReadMsg(pSocket);
if(pMsg == NULL) return;
if (pMsg->m_bClose)
{
CloseSocket(pSocket);
pMsg->m_bClose = FALSE;
break;
}
if(pMsg->m_nType == -1){
UpdateList(pSocket);
}
}
while (!pSocket->m_pArchiveIn->IsBufferEmpty());
}
UpdateClients();
OnUpdateMessages() ;//Update Messages number
OnUpdateConnections() ;//Update Online user
}
CMsg* CChatServerDoc::AssembleMsg(CClientSocket* pSocket)
{
static CMsg msg;
CMsg* tmp;
tmp = m_lsMsg.RemoveHead();
if(tmp != NULL)
memcpy(&msg, tmp, sizeof(CMsg));
return &msg;
}
CMsg* CChatServerDoc::ReadMsg(CClientSocket* pSocket)
{
//read message
static CMsg msg;
CClientSocket* pSock;
TRY
{
pSocket->ReceiveMsg(&msg);
if(msg.m_nType ==-1)
{
bool found=false;
for(POSITION posname=m_connectionList.GetHeadPosition();posname;){
pSock = (CClientSocket*)m_connectionList.GetNext(posname);
if(pSock->name==msg.m_strFrom ){
found=true;
pSocket->needdel=true;
DeleteSocket();
return NULL;
}
}
if(found==false)
{
pSocket->name = msg.m_strFrom;
pSocket->image = msg.m_dImage;
Message("系统信息:",RGB(0,0,0));
Message(msg.m_strFrom,RGB(255,0,0));
Message("风尘仆仆地推门而入!\r\n",RGB(0,0,255));
}
}
else if(msg.m_nType ==-2)
{
Message("系统信息:",RGB(0,0,0));
Message(msg.m_strFrom,RGB(255,0,0));
Message("静静地离开了,孤单的背影显得格外潇洒\r\n",RGB(0,0,255));
}
else if(msg.m_nType==-10)
{
Message("系统信息:",RGB(0,0,0));
Message(msg.m_strText,msg.m_color);
Message("\r\n",RGB(0,0,255));
}
int i = msg.m_nType;
if(i >= 0 && i <= 32)
{
talk(i,msg.m_strFrom,msg.m_strTo,msg.m_strText,msg.m_color);
}
if(i>=-2 && i <= 32)
{
m_lsMsg.AddTail(&msg);
}
}
CATCH(CFileException, e)
{
CString strTemp;
if (strTemp.LoadString(IDS_READERROR))
Message(strTemp,RGB(0,0,0));
msg.m_bClose = TRUE;
pSocket->Abort();
}
END_CATCH
return &msg;
}
void CChatServerDoc::SendMsg(CClientSocket* pSocket, CMsg* pMsg)
{//Send message
TRY
{
pSocket->SendMsg(pMsg);
}
CATCH(CFileException, e)
{
pSocket->Abort();
CString strTemp;
if (strTemp.LoadString(IDS_SENDERROR))
Message(strTemp,RGB(0,0,0));
}
END_CATCH
}
void CChatServerDoc::CloseSocket(CClientSocket* pSocket)
{
//Close Socket
pSocket->Close();
POSITION pos,temp;
for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
temp = pos;
CClientSocket* pSock = (CClientSocket*)m_connectionList.GetNext(pos);
if (pSock == pSocket)
{
m_connectionList.RemoveAt(temp);
break;
}
}
delete pSocket;
}
void CChatServerDoc::Message(LPCTSTR lpszMessage,COLORREF clr)
{
//Display Message
((CChatServerView*)m_viewList.GetHead())->Message(lpszMessage,clr);
}
/////////////////////////////////////////////////////////////////////////////
// CServerDoc Handlers
void CChatServerDoc::OnUpdateMessages()
{
//Update chat messages number
CString strTemp;
wsprintf(strTemp.GetBuffer(50),"信息数: %d",m_lCount);
CMainFrame *MFrame=(CMainFrame *)AfxGetMainWnd();
MFrame->m_wndStatusBar.SetPaneText(2,strTemp);
strTemp.ReleaseBuffer();
}
void CChatServerDoc::OnUpdateConnections()
{
//Update
CString strTemp;
wsprintf(strTemp.GetBuffer(50),"在线人数:%d",m_connectionList.GetCount());
CMainFrame *MFrame=(CMainFrame *)AfxGetMainWnd();
MFrame->m_wndStatusBar.SetPaneText(1,strTemp);
strTemp.ReleaseBuffer();
}
void CChatServerDoc::talk(int type2, CString from1, CString to1, CString str1,COLORREF clr)
{
//Display general message
CString temp,to2,first,second;
if(type2 > 32 || type2 < 0)
return;
if(from1==to1)
{
Message(from1,RGB(255,0,0));
Message("自言自语道:",RGB(0,0,255));
Message(str1,clr);
Message("\r\n",RGB(0,0,0));
return;
}
temp.LoadString(IDS_TALK0 + type2);
int i=temp.Find(",");
if(i!=-1)
{
first=temp.Left(i);
if(i!=temp.GetLength()-1){
second=temp.Mid(i+1);
second+=":";
}
else{
second=":";
}
Message(from1,RGB(0,0,0));
Message(first,RGB(255,0,0));
Message(to1,RGB(0,0,255));
Message(second,RGB(255,0,0));
Message(str1,clr);
Message("\r\n",RGB(0,0,0));
}
else
{
first=temp;
second=": ";
Message(from1,RGB(0,0,0));
Message(first,RGB(255,0,0));
Message(second,RGB(0,0,255));
Message(str1,clr);
Message("\r\n",RGB(0,0,0));
}
}
void CChatServerDoc::DeleteSocket()
{
//delete user
CClientSocket* pSock;
POSITION pos, temp;
for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
temp = pos;
pSock = (CClientSocket*)m_connectionList.GetNext(pos);
if (pSock->needdel==true)
{
m_connectionList.RemoveAt(temp);
break;
}
}
if(pSock==NULL)
return;
CMsg* pMsg = new CMsg;
pMsg->m_strFrom = _TEXT("系统信息:");
pMsg->m_strTo = _TEXT("你");
pMsg->m_bClose = TRUE;
pMsg->m_nType =-9;
pMsg->m_color = RGB(128,0,222);
SendMsg(pSock, pMsg);
if (!pSock->IsAborted()){
pSock->ShutDown();
BYTE Buffer[50];
while (pSock->Receive(Buffer,50) > 0);
delete pSock;
}
}
void CChatServerDoc::UpdateList(CClientSocket* pSocket)//Update user list
{
CMsg* pMsg = new CMsg;
for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;){
CClientSocket* pSock = (CClientSocket*)m_connectionList.GetNext(pos);
pMsg->m_strFrom = pSock->name;
pMsg->m_nType = -8;
pMsg->m_dImage = pSock->image;
SendMsg(pSocket, pMsg);
}
}
void CChatServerDoc::Clean()
{
CCleanDlg clean;
CString name;
if(clean.DoModal()==IDOK){
if(clean.m_cleanname=="") return;
CClientSocket* pSock;
POSITION pos, temp,posname;
bool found=false;
for(posname = m_connectionList.GetHeadPosition(); posname;)
{
pSock = (CClientSocket*)m_connectionList.GetNext(posname);
if(pSock->name == clean.m_cleanname)
found=true;
}
if(!found){
Message("系统信息:",RGB(0,0,0));
Message("不能进行'踢'操作!\r\n",RGB(255,0,0));
return;
}
//type为-7表示把人踢出站外,先给每个人发一个通知,从在线列表里
//删除该人,
CMsg* pMsg = new CMsg;
for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
temp = pos;
pSock = (CClientSocket*)m_connectionList.GetNext(pos);
pMsg->m_bClose = FALSE;
pMsg->m_nType = -7;
pMsg->m_strFrom = clean.m_cleanname;
SendMsg(pSock, pMsg);
}
//第二次通知该人,你已经被踢出了,同时关闭与它的Socket连接
for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
temp = pos;
pSock = (CClientSocket*)m_connectionList.GetNext(pos);
if (pSock->name == clean.m_cleanname)
{
if(pSock == NULL) return;
pMsg->m_bClose = TRUE;
pMsg->m_nType = -5;
pMsg->m_strFrom = clean.m_cleanname;
SendMsg(pSock, pMsg);
m_connectionList.RemoveAt(temp);
if (!pSock->IsAborted())
{
pSock->ShutDown();
BYTE Buffer[50];
while (pSock->Receive(Buffer,50) > 0);
delete pSock;
}
Message("系统信息:",RGB(0,0,0));
Message("聊天室掌门人以一招'佛山无影脚',将",RGB(0,0,255));
Message(clean.m_cleanname,RGB(255,0,255));
Message("踢出门外\r\n",RGB(0,0,255));
}
}
delete pMsg;
}
}
void CChatServerDoc::OnServerBrandcast()
{
// TODO: Add your command handler code here
//Send BroadCast
CBrandCast dlg;
if(dlg.DoModal()!=IDOK)
{
return;
}
CMsg* pMsg = new CMsg;
pMsg->m_color=RGB(0,0,0);
pMsg->m_strFrom="系统信息:";
pMsg->m_strText=dlg.m_strBrandCast;
pMsg->m_strTo=" 所有人";
pMsg->m_nType=-10;
for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos);
if (pMsg != NULL)
SendMsg(pSocket, pMsg);
}
Message("系统信息:",pMsg->m_color);
Message(pMsg->m_strText,pMsg->m_color);
Message("\r\n",pMsg->m_color);
delete pMsg;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?