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

📄 chattermgr.cpp

📁 带文件传输功能的聊天室,可多人聊天,也可私聊,任意用户间可互传文件
💻 CPP
字号:
// ChatterMgr.cpp: implementation of the CChatterMgr class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "chatter.h"
#include "ChatterMgr.h"
#include "logindlg.h"
#include "waiting.h"
#include "clientsocket.h"
#include "filetransfer.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CChatterMgr *CChatterMgr::s_pChatter = NULL;
CChatterMgr *CChatterMgr::GetChatterMgr()
{
	if(s_pChatter == NULL)
	{
		s_pChatter = new CChatterMgr;
	}
	return s_pChatter;
}


CChatterMgr::CChatterMgr()
{
	CoInitialize(NULL); 
	
	m_nIndex = 0;
	m_pSocket = new CClientSocket;

	m_bConnected = FALSE;
	m_hConnectEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_hLoginEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

	m_pChatterDlg = NULL;

	m_cmd.SetLoginSuccessFunc(LoginSuccessFunc);
	m_cmd.SetLogoutFunc(LogoutFunc);
	m_cmd.SetNewUserFunc(NewUserFunc);
	m_cmd.SetUserMessageFunc(UserMessageFunc);
	
	m_lpMapUsers = NULL;
	m_cmd.SetType(this);
	
}

CChatterMgr::~CChatterMgr()
{
	CoUninitialize(); 

	m_pSocket->ShutDown(2);	
	m_pSocket->Close();
	delete m_pSocket;

	m_pChatterDlg = NULL;
	CloseHandle(m_hConnectEvent);
	CloseHandle(m_hLoginEvent);

	POSITION pos = m_lpMapUsers->GetStartPosition();
	for(;pos!=NULL;)
	{
		LONG id;
		LPUSERINFO lpUser;
		m_lpMapUsers->GetNextAssoc(pos, id, lpUser);
		m_lpMapUsers->RemoveKey(id);
		delete lpUser;
	}
}

BOOL CChatterMgr::Login()
{
	//初始化socket
	if(!m_pSocket->Create())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED, MB_OK|MB_ICONSTOP);
		delete m_pSocket;
		m_pSocket = NULL;
		return FALSE;
	}
	
	//登陆
	CLoginDlg dlg;
	
	while(TRUE)
	{

		if (IDOK != dlg.DoModal())
		{
			return FALSE;
		}
		
		if (!DoConnect(dlg.m_strUser, dlg.m_strServer, dlg.m_nPort))
		{
			m_pSocket->ShutDown(2);

			//连接失败
			if (AfxMessageBox(IDS_RETRYCONNECT,MB_YESNO) == IDNO)
			{
				return FALSE;
			}
		}
		else
			break;
	}	
	
	return TRUE;	
}

BOOL CChatterMgr::DoConnect(LPCTSTR lpszUser, LPCTSTR lpszServer, UINT nPort)
{
	//显示连接提示对话框
	CWaiting waiting;
	
	sprintf(m_user.m_name,lpszUser);
	memset(m_user.m_ip,0, sizeof(m_user.m_ip));
	m_user.m_nPort = 0;

	//连接服务器
	if(!m_pSocket->Connect(lpszServer, nPort))
	{
		if(WSAEWOULDBLOCK != WSAGetLastError())
		{
			PRINTDEBUG(FALSE);
			m_pSocket->Close();
			return FALSE;
		}
	}
	
	//等待连接事件发生
	if(!waiting.DoWaiting(m_hConnectEvent, INFINITE))
		return FALSE;
	
	//是否连接成功,否:返回FALSE
	if(!IsConnected())	return FALSE;	
	
	//登陆
	DoLogin();
	
	waiting.SetPrompt("认证用户...");
	
	
	//等待注册,超时设定20秒
	if(!waiting.DoWaiting(m_hLoginEvent, 5000))
		return FALSE;
	
	CString str;
	m_pChatterDlg->GetWindowText(str);
	m_pChatterDlg->SetWindowText(str+" [ "+CString(m_user.m_name)+" ] ");

	return TRUE;
}
void CChatterMgr::OnConnect(int nErrorCode)
{
	if(nErrorCode == 0)
	{
		SetConnected();
	}
	SetEvent(m_hConnectEvent);
}

//登陆
void CChatterMgr::DoLogin()
{
	//初始化监听文件传输socket
	SOCKET s = socket(AF_INET, SOCK_STREAM,IPPROTO_IP);
	
	SOCKADDR_IN sockAddr;
	memset(&sockAddr,0,sizeof(sockAddr));
	int nSize = sizeof(sockAddr);
	sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);	
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_port = htons((u_short)0);

	bind(s, (sockaddr*)&sockAddr, nSize);

	getsockname(s, (sockaddr*)&sockAddr, &nSize);

	m_user.m_nFilePort = ntohs(sockAddr.sin_port);
	
	//启动监听线程
	AfxBeginThread(AcceptFunc, (LPVOID)s);		

	CString strCmd = m_cmd.CreateUserLogin(m_user);
	SendMsg(strCmd);	
}

//发言
void CChatterMgr::DoSay(USERINFO &user, LPCSTR lpszSay) 
{	
	CString strCmd = m_cmd.CreateUserSpeak(m_user, user, lpszSay);	
	SendMsg(strCmd);	
}


void CChatterMgr::SendMsg(CString strCmd)
{
	m_pSocket->Send(strCmd, strCmd.GetLength());
}

//处理接收到的数据
void CChatterMgr::ProcessReceiveData(LPCSTR lpData)
{
	//新接收到数据写入缓存
	m_buffer.Write(lpData, strlen(lpData));
	printf("recv data:%s\n", lpData);
	//获取指令
	try
	{
		CString strXML;
		while(m_cmd.HasNetPacket(m_buffer, strXML))
		{
			m_cmd.DoProcessNetPacket(m_user.m_id, strXML);
		}
	}
	catch (_com_error &e)
	{
		AfxMessageBox((char*)e.Description());
	}
}

//以下是call back 函数
void CChatterMgr::LogoutFunc(USERINFO &user)
{
	LPUSERINFO lpUser;
	if(m_lpMapUsers->Lookup(user.m_id, lpUser))
	{
		m_pChatterDlg->DeleteUser(*lpUser);
		delete lpUser;
	}
	DoServerMessage("["+CString(user.m_name)+"] 离开聊天室");
	
}

void CChatterMgr::NewUserFunc(USERINFO &user)
{
	(*m_lpMapUsers)[user.m_id] = &user;	
	m_pChatterDlg->AddUser(&user);

	char port[10];
	sprintf(port, "%d", user.m_nPort);
	DoServerMessage("欢迎 ["+CString(user.m_name)+"] 从 ["+ user.m_ip +":"+port+"] 进入聊天室");
}

void CChatterMgr::UserMessageFunc(USERINFO &userSrc,USERINFO &userDest, CString strMessage)
{
	CString strSrc(userSrc.m_name);
	CString strDest(userDest.m_name);
	CString str = "["+strSrc+"]" + " 对 [" + strDest + "] 说: "+strMessage;
	DoUserMessage(str);
}

void CChatterMgr::LoginSuccessFunc(USERINFO &user, MAPUSER *lpMapUser)
{
	SetEvent(m_hLoginEvent);

	m_user.m_id = user.m_id;
	m_user.m_nPort = user.m_nPort;
	sprintf(m_user.m_ip, user.m_ip);
	m_lpMapUsers = lpMapUser;

	//添加自己
	m_pChatterDlg->AddUser(&m_user, FALSE);	

	//用户列表	
	POSITION pos = m_lpMapUsers->GetStartPosition();
	for(;pos!=NULL;)
	{
		LONG id;
		LPUSERINFO lpUser;
		m_lpMapUsers->GetNextAssoc(pos, id, lpUser);
		//添加其他人
		m_pChatterDlg->AddUser(lpUser);	
	}
	
	char port[10];
	sprintf(port, "%d", user.m_nPort);
	DoServerMessage("欢迎 ["+CString(user.m_name)+"] 从 ["+ user.m_ip +":"+port+"] 进入聊天室");
}

void CChatterMgr::SendFile(LONG id, CString strFile)
{
	//获得选中的用户
	LPUSERINFO lpUser;
	if(!m_lpMapUsers->Lookup(id, lpUser))
	{
		lpUser = &m_user;
	}
	LPFILETRANSFER lpF = new FILETRANSFER;
	lpF->m_lpUser = lpUser;
	strcpy(lpF->m_fileName, strFile);

	AfxBeginThread(ConnectFunc, (LPVOID)lpF);

}

DWORD CChatterMgr::AddTP(LPCSTR strName, DWORD nMaxRange)
{
	CSingleLock lock(&m_cs);
	lock.Lock();

	DWORD nIndex = m_nIndex;
	SendMessage(m_pChatterDlg->GetSafeHwnd(), WM_ADDPROGRESS, nIndex, nMaxRange);
	SendMessage(m_pChatterDlg->GetSafeHwnd(), WM_SETLABEL, nIndex, (WPARAM)strName);
	
	m_nIndex++;

	lock.Unlock();
	
	return nIndex;

}

//设置步长
void CChatterMgr::SetTPStep(DWORD nIndex, DWORD nPos)
{
	SendMessage(m_pChatterDlg->GetSafeHwnd(), WM_SETPOS, nIndex, nPos);	
}
//设置速度提示
void CChatterMgr::SetTPVelocity(DWORD nIndex, DWORD nVelocity)
{
	SendMessage(m_pChatterDlg->GetSafeHwnd(), WM_SETVELOCITY, nIndex, nVelocity);	
}

void CChatterMgr::DeleteTP(DWORD nIndex)
{
	SendMessage(m_pChatterDlg->GetSafeHwnd(), WM_DELPROGRESS, nIndex, 0);
}

⌨️ 快捷键说明

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