www.pudn.com > ChatSystem_src.zip > ChatServerDoc.cpp


// ChatServerDoc.cpp : implementation of the CChatServerDoc class 
// 
 
#include "stdafx.h" 
#include "ChatServer.h" 
 
#include "ChatServerDoc.h" 
#include "SrvrItem.h" 
 
#include "MainFrm.h" 
#include "ChatView.h" 
#include "LeftView.h" 
 
#include "PortDlg.h" 
#include "Msg.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
#define JOINING_CHAT          1 
#define LEAVING_CHAT          2 
#define SENDING_CHATTERS_LIST 3 
#define SENDING_NICKNAME      4 
#define NORMAL_MESSAGE        5 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatServerDoc 
 
IMPLEMENT_DYNCREATE(CChatServerDoc, COleServerDoc) 
 
BEGIN_MESSAGE_MAP(CChatServerDoc, COleServerDoc) 
	//{{AFX_MSG_MAP(CChatServerDoc) 
		// NOTE - the ClassWizard will add and remove mapping macros here. 
		//    DO NOT EDIT what you see in these blocks of generated code! 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatServerDoc construction/destruction 
 
CChatServerDoc::CChatServerDoc() 
{ 
	// Use OLE compound files 
	EnableCompoundFile(); 
	m_pSocket = NULL; 
	m_chattersList.RemoveAll(); 
	// TODO: add one-time construction code here 
 
} 
 
CChatServerDoc::~CChatServerDoc() 
{ 
} 
 
BOOL CChatServerDoc::OnNewDocument() 
{ 
	if (!COleServerDoc::OnNewDocument()) 
		return FALSE; 
 
 
	CPortDlg Dialog; 
 
	if (Dialog.DoModal() == IDOK) 
	{ 
		m_pSocket = new CListeningSocket(this); 
		if (m_pSocket->Create(Dialog.m_nPort+1500)) // 700 
		{ 
			if (m_pSocket->Listen()) 
				return TRUE; 
		} 
	} 
	return FALSE; 
 
	// TODO: add reinitialization code here 
	// (SDI documents will reuse this document) 
 
	return TRUE; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatServerDoc server implementation 
 
COleServerItem* CChatServerDoc::OnGetEmbeddedItem() 
{ 
	// OnGetEmbeddedItem is called by the framework to get the COleServerItem 
	//  that is associated with the document.  It is only called when necessary. 
 
	CChatServerSrvrItem* pItem = new CChatServerSrvrItem(this); 
	ASSERT_VALID(pItem); 
	return pItem; 
} 
 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatServerDoc serialization 
 
void CChatServerDoc::Serialize(CArchive& ar) 
{ 
	if (ar.IsStoring()) 
	{ 
		// CEditView contains an edit control which handles all serialization 
		((CEditView*)m_viewList.GetHead())->SerializeRaw(ar); 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatServerDoc diagnostics 
 
#ifdef _DEBUG 
void CChatServerDoc::AssertValid() const 
{ 
	COleServerDoc::AssertValid(); 
} 
 
void CChatServerDoc::Dump(CDumpContext& dc) const 
{ 
	COleServerDoc::Dump(dc); 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatServerDoc commands 
 
void CChatServerDoc::DeleteContents() 
{ 
	if(m_pSocket == (CListeningSocket*)NULL) 
		return; 
	 
	delete m_pSocket; 
	m_pSocket = NULL; 
 
	CString temp; 
	if (temp.LoadString(IDS_SERVERSHUTDOWN)) 
		m_msgList.AddTail(temp); 
 
	while(!m_connectionList.IsEmpty()) 
	{ 
		CClientSocket* pSocket = (CClientSocket*)m_connectionList.RemoveHead(); 
		CMsg* pMsg = AssembleMsg(pSocket); 
		pMsg->m_bClose = TRUE; 
 
		SendMsg(pSocket, pMsg); 
 
		if (!pSocket->IsAborted()) 
		{ 
			pSocket->ShutDown(); 
 
			BYTE Buffer[50]; 
 
			while (pSocket->Receive(Buffer,50) > 0); 
 
			delete pSocket; 
		} 
	} 
 
	m_msgList.RemoveAll(); 
 
	if (!m_viewList.IsEmpty()) 
		Message(""); 
 
	CDocument::DeleteContents(); 
} 
 
void CChatServerDoc::SendUpdatedList(CMsg* pMsg) 
{ 
	for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;) 
	{ 
		CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos); 
		if (pMsg != NULL) 
			SendMsg(pSocket, pMsg); 
	} 
} 
 
void CChatServerDoc::UpdateClients() 
{ 
	for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;) 
	{ 
		CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos); 
		CMsg* pMsg = AssembleMsg(pSocket); 
 
		if (pMsg != NULL) 
			SendMsg(pSocket, pMsg); 
	} 
} 
 
void CChatServerDoc::ProcessPendingAccept() 
{ 
	CClientSocket* pSocket = new CClientSocket(this); 
 
	if (m_pSocket->Accept(*pSocket)) 
	{ 
		pSocket->Init(); 
		m_connectionList.AddTail(pSocket); 
		UpdateConnections(); 
	}	 
	else 
		delete pSocket; 
} 
 
void CChatServerDoc::ProcessPendingRead(CClientSocket* pSocket) 
{ 
	CMsg* pMsg; 
 
	bIsNewChatter = FALSE; 
	do 
	{ 
		pMsg = ReadMsg(pSocket); 
		if(pMsg->code == SENDING_NICKNAME) 
		{ 
			bIsNewChatter = TRUE; 
		} 
 
		if (pMsg->m_bClose) 
		{ 
			CloseSocket(pSocket); 
			break; 
		} 
	} 
	while (!pSocket->m_pArchiveIn->IsBufferEmpty()); 
 
	if(bIsNewChatter) 
	{ 
		pMsg->code = SENDING_CHATTERS_LIST; 
		pMsg->m_chattersList.AddTail(pMsg->m_strText); 
		SendUpdatedList(pMsg); 
		bIsNewChatter = FALSE; 
	} 
 
	UpdateClients(); 
} 
 
CMsg* CChatServerDoc::AssembleMsg(CClientSocket* pSocket) 
{ 
	static CMsg msg; 
 
	msg.Init(); 
 
	if (pSocket->m_nMsgCount >= m_msgList.GetCount()) 
		return NULL; 
 
	for (POSITION pos1 = m_msgList.FindIndex(pSocket->m_nMsgCount); pos1 != NULL;) 
	{ 
		CString temp = m_msgList.GetNext(pos1); 
		msg.m_msgList.AddTail(temp); 
	} 
	pSocket->m_nMsgCount = m_msgList.GetCount(); 
	UpdateMessages(); 
	return &msg; 
} 
 
CMsg* CChatServerDoc::ReadMsg(CClientSocket* pSocket) 
{ 
	static CMsg msg; 
 
	TRY 
	{ 
		pSocket->ReceiveMsg(&msg); 
 
		if(msg.code == SENDING_NICKNAME) 
		{ 
			UpdateChattersList(msg.m_strText); 
		} 
		if(msg.code == LEAVING_CHAT) 
		{ 
			DeleteChatter(msg.m_strText, &msg); 
		} 
		if(msg.code == NORMAL_MESSAGE) 
		{ 
			Message(msg.m_strText); 
			m_msgList.AddTail(msg.m_strText); 
		} 
	} 
	CATCH(CFileException, e) 
	{ 
		CString strTemp; 
		if (strTemp.LoadString(IDS_READERROR)) 
			Message(strTemp); 
 
		msg.m_bClose = TRUE; 
		pSocket->Abort(); 
	} 
	END_CATCH 
 
	return &msg; 
} 
 
void CChatServerDoc::SendMsg(CClientSocket* pSocket, CMsg* pMsg) 
{ 
	TRY 
	{ 
		pSocket->SendMsg(pMsg); 
	} 
	CATCH(CFileException, e) 
	{ 
		pSocket->Abort(); 
 
		CString strTemp; 
		if (strTemp.LoadString(IDS_SENDERROR)) 
			Message(strTemp); 
	} 
	END_CATCH 
} 
 
void CChatServerDoc::CloseSocket(CClientSocket* pSocket) 
{ 
	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; 
		} 
	} 
 
	UpdateConnections(); 
	delete pSocket; 
} 
 
void CChatServerDoc::Message(LPCTSTR lpszMessage) 
{ 
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;) 
	{ 
		CView* pView = GetNextView(pos); 
		CChatView* pChatView = DYNAMIC_DOWNCAST(CChatView, pView); 
 
		if (pChatView != NULL) 
			pChatView->message(lpszMessage); 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CServerDoc Handlers 
 
void CChatServerDoc::UpdateMessages() 
{ 
	CMainFrame* cwnd = (CMainFrame*)AfxGetMainWnd(); 
	if(cwnd != NULL) 
		cwnd->m_MessageCount = m_msgList.GetCount(); 
} 
 
void CChatServerDoc::UpdateConnections() 
{ 
	CMainFrame* cwnd = (CMainFrame*)AfxGetMainWnd(); 
	cwnd->m_ConnectionCount = m_connectionList.GetCount(); 
} 
 
void CChatServerDoc::UpdateChattersList(CString sName) 
{ 
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;) 
	{ 
		CView* pView = GetNextView(pos); 
		CLeftView* pChatView = DYNAMIC_DOWNCAST(CLeftView, pView); 
 
		if (pChatView != NULL) 
			pChatView->UpdateChatters(sName); 
	}	 
} 
 
void CChatServerDoc::DeleteChatter(CString sNickName, CMsg* pMsg) 
{ 
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;) 
	{ 
		CView* pView = GetNextView(pos); 
		CLeftView* pChatView = DYNAMIC_DOWNCAST(CLeftView, pView); 
 
		if (pChatView != NULL) 
			pChatView->DeleteChatter(sNickName); 
	}	 
 
	int i; 
	for(i = 0 ; i < pMsg->m_chattersList.GetCount(); i++) 
	{ 
		pos = pMsg->m_chattersList.FindIndex(i); 
		CString sName = pMsg->m_chattersList.GetAt(pos); 
		if(sName == sNickName) 
		{ 
			pMsg->m_chattersList.RemoveAt(pos); 
			pMsg->code = SENDING_CHATTERS_LIST; 
			SendUpdatedList(pMsg); 
			break; 
		} 
 
	} 
 
}