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

📄 chatclientdoc.cpp

📁 利用CSocket类编写的一个网络聊天程序,加深对CSocket类的基本应用的认识.
💻 CPP
字号:
// ChatClientDoc.cpp : implementation of the CChatClientDoc class
//

#include "stdafx.h"
#include "ChatClient.h"

#include "ChatClientDoc.h"
#include "Msg.h"
#include "ChatSocket.h"
#include "MessageView.h"
#include "ChattersView.h"
#include "LogDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define LEAVING_CHAT          1
#define SENDING_CHATTERS_LIST 2
#define SENDING_NICKNAME      3
#define NORMAL_MESSAGE        4
#define USED_NAME			  5
/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc

IMPLEMENT_DYNCREATE(CChatClientDoc, CDocument)

BEGIN_MESSAGE_MAP(CChatClientDoc, CDocument)
	//{{AFX_MSG_MAP(CChatClientDoc)
	ON_COMMAND(ID_CONNECT, OnConnect)
	ON_UPDATE_COMMAND_UI(ID_CONNECT, OnUpdateConnect)
	ON_COMMAND(ID_DISCONNECT, OnDisconnect)
	ON_UPDATE_COMMAND_UI(ID_DISCONNECT, OnUpdateDisconnect)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc construction/destruction

CChatClientDoc::CChatClientDoc()
{
	// TODO: add one-time construction code here
	bIsConnected = FALSE;
	m_pSocket = NULL;
	m_pFile = NULL;
	m_pArchiveOut = NULL;
	m_pArchiveIn = NULL;
}

CChatClientDoc::~CChatClientDoc()
{
}

BOOL CChatClientDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc serialization

void CChatClientDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc diagnostics

#ifdef _DEBUG
void CChatClientDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CChatClientDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc commands

void CChatClientDoc::OnConnect() 
{
	// TODO: Add your command handler code here
	CLogDlg dlg;
	if(dlg.DoModal() == IDOK)
	{
		if(ConnectSocket(dlg.m_Name, dlg.m_Server, dlg.m_Port))
			bIsConnected = TRUE;
		else
			AfxMessageBox("连接服务器失败!");
			
	}
}


void CChatClientDoc::OnUpdateConnect(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(!bIsConnected);
}

void CChatClientDoc::OnDisconnect() 
{
	// TODO: Add your command handler code here
	DeleteContents();
	bIsConnected = FALSE;
}

void CChatClientDoc::OnUpdateDisconnect(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(bIsConnected);
}

BOOL CChatClientDoc::ConnectSocket(LPCTSTR lpszHandle, LPCTSTR lpszAddress, int nPort)
{
	m_strName = lpszHandle;
	m_pSocket = new CChatSocket(this);
	//创建socket失败
	if (!m_pSocket->Create())
	{
		delete m_pSocket;
		m_pSocket = NULL;
		AfxMessageBox("创建socket失败!");
		return FALSE;
	}
	//连接失败
	if(!m_pSocket->Connect(lpszAddress, nPort))
	{
		delete m_pSocket;
		m_pSocket = NULL;
		return FALSE;
	}

	m_pFile = new CSocketFile(m_pSocket);
	//用于数据接收和发送
	m_pArchiveIn = new CArchive(m_pFile,CArchive::load);
	m_pArchiveOut = new CArchive(m_pFile,CArchive::store);
	//将用户名发送给服务器
	SendMsg(m_strName, SENDING_NICKNAME, false);
	
	CString strTemp;
	strTemp.Format("进入聊天室");
	//作为普通消息发送给服务器
	SendMsg(strTemp, NORMAL_MESSAGE, true);
	return TRUE;
}

void CChatClientDoc::SendMsg(CString& strText, int mCode, BOOL bSendHandle)
{
	if (m_pArchiveOut != NULL)
	{
		CMsg msg;
		msg.code = mCode;
		msg.m_strText = (bSendHandle ? m_strName + _T(": ") + strText : strText);
		TRY
		{
			msg.Serialize(*m_pArchiveOut);
			m_pArchiveOut->Flush();
		}
		CATCH(CFileException, e)
		{
			m_pArchiveOut->Abort();
			delete m_pArchiveOut;
			m_pArchiveOut = NULL;
			CString strTemp;
			strTemp.Format("发送失败");
			DisplayMsg(strTemp);
		}
		END_CATCH
	}
}

void CChatClientDoc::ProcessReceive()
{
	do
	{
		ReceiveMsg();
		if (m_pSocket == NULL)
			return;
	}
	while(!m_pArchiveIn->IsBufferEmpty());
}

void CChatClientDoc::ReceiveMsg()
{
	CMsg msg;
	TRY
	{
		msg.Serialize(*m_pArchiveIn);
		if(msg.code == SENDING_CHATTERS_LIST)
		{
			//更新用户列表
			UpdateChattersList(&msg);
			return;
		}
		if(msg.code == USED_NAME)
		{
			//如果是用户名已存在信息则关闭连接,退出
			AfxMessageBox(msg.m_strText);
			msg.m_bClose = TRUE;
			OnDisconnect();
			return;
		}
		//显示消息
		DisplayMsg(msg.m_strText);
	}
	CATCH(CFileException, e)
	{
		msg.m_bClose = TRUE;
		m_pArchiveOut->Abort();
		CString strTemp;
		strTemp.Format("接收数据失败");
		DisplayMsg(strTemp);
	}
	END_CATCH
	//如果连接已关闭则删除各对象
	if (msg.m_bClose)
	{
		delete m_pArchiveIn;
		m_pArchiveIn = NULL;
		delete m_pArchiveOut;
		m_pArchiveOut = NULL;
		delete m_pFile;
		m_pFile = NULL;
		delete m_pSocket;
		m_pSocket = NULL;
	}
}

void CChatClientDoc::DisplayMsg(LPCTSTR lpszText)
{
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);
		CMessageView* pChatView = DYNAMIC_DOWNCAST(CMessageView, pView);
		if (pChatView != NULL)
			pChatView->ShowMessage(lpszText);
	}
}

void CChatClientDoc::UpdateChattersList(CMsg* pMsg)
{
	CChattersView* pChattersView;
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);
		pChattersView = DYNAMIC_DOWNCAST(CChattersView, pView);
		//首先清空用户列表视图
		if (pChattersView != NULL)
			pChattersView->ClearChattersList();
	}	
	CString strTemp = pMsg->m_strText;
	//得到所有的用户名并加入到用户列表中
	do
	{
		CString sName = strTemp.Left(strTemp.Find(":",0));
		pChattersView->AddToChattersList(sName);
		strTemp = strTemp.Mid(strTemp.Find(":" , 0)+1);
	}while(strTemp.Find(":",0) != -1);
}

void CChatClientDoc::DeleteContents()
{
	if ((m_pSocket != NULL) && (m_pFile != NULL) && (m_pArchiveOut != NULL))
	{
		//首先发送用户名
		SendMsg(m_strName, LEAVING_CHAT, false);
		CMsg msg;
		CString strTemp;
		//发送普通消息
		strTemp.Format(":离开了聊天室");
		msg.code = NORMAL_MESSAGE;
		msg.m_bClose = TRUE;
		msg.m_strText = m_strName + strTemp;
		msg.Serialize(*m_pArchiveOut);
		m_pArchiveOut->Flush();	
	}
	//删除各对象
	delete m_pArchiveOut;
	m_pArchiveOut = NULL;
	delete m_pArchiveIn;
	m_pArchiveIn = NULL;
	delete m_pFile;
	m_pFile = NULL;
	//关闭连接
	if (m_pSocket != NULL)
	{
		m_pSocket->ShutDown(2);
		delete m_pSocket;
		m_pSocket = NULL;
	}
	//更新视图
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);

		if (pView->IsKindOf(RUNTIME_CLASS(CMessageView)))
		{
			CMessageView* pChatView = (CMessageView*)pView;
			pChatView->GetEditCtrl().SetWindowText(_T(""));
		}
		if (pView->IsKindOf(RUNTIME_CLASS(CChattersView)))
		{
			CChattersView* pCChattersView = (CChattersView*)pView;
			pCChattersView->ClearChattersList();
		}
	}
	CDocument::DeleteContents();
}

⌨️ 快捷键说明

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