⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chatserverdoc.cpp

📁 一个简易的聊天室程序
💻 CPP
字号:
// ChatServerDoc.cpp : implementation of the CChatServerDoc class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
// 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 "ChattersListView.h"

#include "PortDlg.h"
#include "Msg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// 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_pChattersList.RemoveAll();
	m_chattersListPtr.RemoveAll();

	m_msgPtr.RemoveAll();

	m_stdCF.cbSize = sizeof(CHARFORMAT);
	m_stdCF.dwMask = 0;
	m_stdCF.dwEffects = 0;
	m_stdCF.yHeight = 0;
	m_stdCF.yOffset = 0;
	m_stdCF.crTextColor = RGB(255,0,0);
	m_stdCF.bCharSet = 0;
	m_stdCF.bPitchAndFamily = 0;
	strcpy(m_stdCF.szFaceName, "Arial");

}

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;
}

/////////////////////////////////////////////////////////////////////////////
// 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);
	}

	CMsg* pMsg = new CMsg();
	pMsg->Init();
	pMsg->m_msgList.AddTail(temp);
	pMsg->code = NORMAL_MESSAGE;
	pMsg->m_bClose = TRUE;
	while(!m_connectionList.IsEmpty())
	{
		CClientSocket* pSocket = (CClientSocket*)m_connectionList.RemoveHead();

		SendMsg(pSocket, pMsg);

		if (!pSocket->IsAborted())
		{
			pSocket->ShutDown();

			BYTE Buffer[50];

			while (pSocket->Receive(Buffer,50) > 0);

			delete pSocket;
		}
	}


	CDocument::DeleteContents();
}

void CChatServerDoc::SendUpdatedList(CClientSocket* pSocket)
{
	POSITION pos;
	CMsg* pMsg = new CMsg();
	pMsg->Init();
	for(pos = m_pChattersList.GetHeadPosition(); pos != NULL;)
	{
		CString tempName = m_pChattersList.GetNext(pos);
		pMsg->m_chattersList.AddTail(tempName);
	}


	pMsg->code = SENDING_CHATTERS_LIST;
	for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
	{
		CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos);
		if (pSocket != NULL)
			SendMsg(pSocket, pMsg);
	}
}

void CChatServerDoc::UpdateClients(int nCode)
{
	for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;)
	{
		CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos);
		CMsg* pMsg = AssembleMsg(pSocket, nCode);
		if (pMsg != NULL)
		{
			pMsg->code = nCode;
			SendMsg(pSocket, pMsg);
		}
	}
}

void CChatServerDoc::ProcessPendingAccept()
{
	CClientSocket* pSocket = new CClientSocket(this);

	if (!m_pSocket->Accept(*pSocket))
	{
		delete pSocket;
	}
	else
	{
		pSocket->Init();
		CMsg* msg = new CMsg();
		pSocket->ReceiveMsg(msg);
		CString cNickName = msg->m_strText;
		if(DuplicateName(cNickName))
		{
			CMsg* mmsg = new CMsg;
			mmsg->Init();
			mmsg->code =  DUPLICATE_NICKNAME;
			CString string;
			string.LoadString(IDS_NICKINUSE);
			mmsg->m_strText = string;
			SendMsg(pSocket , mmsg);
			pSocket->ShutDown();
			BYTE Buffer[50];

			while (pSocket->Receive(Buffer,50) > 0);

			delete pSocket;
		}
		else
		{
			pSocket->m_ChattersName = cNickName;
			UpdateChattersNames(cNickName, pSocket);
			m_connectionList.AddTail(pSocket);
			UpdateConnections();
			SendUpdatedList(pSocket);
			UpdateChattersList(cNickName, pSocket);
		}
	}	

}

void CChatServerDoc::ProcessPendingRead(CClientSocket* pSocket)
{
	CMsg* pMsg;
	do
	{
		pMsg = ReadMsg(pSocket);
		if((pMsg->code == PRIVATE_MESSAGE) || (pMsg->code == KICK_USER))
		{
			CClientSocket* cSock = (CClientSocket*)CAsyncSocket::FromHandle(pMsg->m_hSocket);
			SendMsg(cSock , pMsg);
		}
		
		if(pMsg->m_bClose)
		{
			CString cNickName = pSocket->m_ChattersName;
			UpdateClients(LEAVING_CHAT);
			DeleteChatter(pMsg , cNickName);
			CloseSocket(pSocket);
			SendUpdatedList(pSocket);
			break;
		}
		else
			UpdateClients(NORMAL_MESSAGE);
	}
	while (!pSocket->m_pArchiveIn->IsBufferEmpty());

}

CMsg* CChatServerDoc::AssembleMsg(CClientSocket* pSocket , int nCode)
{
	static CMsg msg;
	msg.Init();
	if (pSocket->m_nMsgCount >= m_msgPtr.GetCount())
		return NULL;

	CString tempPrev = _T("");
	for (POSITION pos = m_msgPtr.FindIndex(pSocket->m_nMsgCount); pos != NULL;)
	{
		CMsg* msg1 = (CMsg*)m_msgPtr.GetNext(pos);
		CString temp = msg1->m_strText;
		if(tempPrev != temp)
		{
			msg.m_msgList.AddTail(temp);
			msg.m_dwMask            = msg1->m_dwMask;
			msg.m_dwEffects         = msg1->m_dwEffects;
			msg.m_yHeight           = msg1->m_yHeight;
			msg.m_yOffset           = msg1->m_yOffset;
			msg.m_crTextColor       = msg1->m_crTextColor;
			msg.m_bCharSet          = msg1->m_bCharSet;
			msg.m_bPitchAndFamily   = msg1->m_bPitchAndFamily;
			msg.m_szFaceName        = msg1->m_szFaceName;

			msg.code = nCode;
		}

		tempPrev = temp;
	}
	pSocket->m_nMsgCount = m_msgPtr.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 , pSocket);
		}
		if(msg.code == NORMAL_MESSAGE)
		{

			CHARFORMAT2 cf;
			cf.cbSize            =  sizeof(CHARFORMAT2);
			cf.dwMask            =	msg.m_dwMask;
			cf.dwEffects         =	msg.m_dwEffects;
			cf.yHeight           = 	msg.m_yHeight;
			cf.yOffset           = 	msg.m_yOffset;
			cf.crTextColor       =	msg.m_crTextColor;
			cf.bCharSet          = 	msg.m_bCharSet;
			cf.bPitchAndFamily   = 	msg.m_bPitchAndFamily;
			strcpy(cf.szFaceName,	msg.m_szFaceName);

			Message(msg.m_strText , cf);
			m_msgList.AddTail(msg.m_strText);
			
			m_msgPtr.AddTail(&msg);
		
		}
	}
	CATCH(CFileException, e)
	{
		CString strTemp;
		if (strTemp.LoadString(IDS_READERROR))
			Message(strTemp ,  m_stdCF);

		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,  m_stdCF);
	}
	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;
	if(m_connectionList.GetCount() == 0)
	{
		m_msgList.RemoveAll();
		m_pChattersList.RemoveAll();
	}
}

void CChatServerDoc::Message(LPCTSTR lpszMessage, CHARFORMAT cf)
{
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);
		CChatView* pChatView = DYNAMIC_DOWNCAST(CChatView, pView);

		if (pChatView != NULL)
			pChatView->message(lpszMessage, cf);
	}
}

/////////////////////////////////////////////////////////////////////////////
// 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, CClientSocket* pSocket)
{

	CAsyncSocket* cSocket = (CAsyncSocket*)pSocket;
	CString sIPAddress;
	UINT iPort;
	cSocket->GetPeerName(sIPAddress , iPort);
	
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);
		CChattersListView* pChattersListView = DYNAMIC_DOWNCAST(CChattersListView, pView);

		if (pChattersListView != NULL)
			pChattersListView->UpdateChatters(sName , sIPAddress , iPort);
	}	
}

void CChatServerDoc::DeleteChatter(CMsg* pMsg, CString sName)
{

	POSITION pos;
	for(pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);
		CChattersListView* pChattersListView = DYNAMIC_DOWNCAST(CChattersListView, pView);

		if (pChattersListView != NULL)
			pChattersListView->DeleteChatter(sName);
	}	

	POSITION temp;
	for(pos = m_pChattersList.GetHeadPosition(); pos != NULL;)
	{
		temp = pos;
		CString tempName = (CString)m_pChattersList.GetNext(pos);
        // Strip out Socket from Name
		tempName = tempName.Left(tempName.Find(":",0));
		if(sName == tempName)
			m_pChattersList.RemoveAt(temp);
	}

}

void CChatServerDoc::UpdateChattersNames(CString sName , CClientSocket* pSocket)
{
	CString sock, string;
	sock.Format("%d" , pSocket->m_hSocket);
	sName += "::" + sock;
	m_pChattersList.AddTail(sName);
}

BOOL CChatServerDoc::DuplicateName(CString sNickName)
{
	return (m_pChattersList.Find(sNickName, NULL) == NULL ? FALSE : TRUE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -