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

📄 clientsocket.cpp

📁 面向软件工程的Visual C++网络程序开发
💻 CPP
字号:
// ClientSocket.cpp : implementation file

#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"

#include "ClientSocket.h"
#include "..\\Common.h"

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

/////////////////////////////////////////////////////////////////////////////
// CClientSocket

CClientSocket::CClientSocket(CClientDlg* pDlg)
{
	m_pMainWnd = pDlg;
}

CClientSocket::~CClientSocket()
{
}


// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CClientSocket, CAsyncSocket)
	//{{AFX_MSG_MAP(CClientSocket)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif	// 0

/////////////////////////////////////////////////////////////////////////////
// CClientSocket member functions

//--------------------------------------------------------------------------- 
//--------------------------------------------------------------------------- 
void CClientSocket::OnConnect(int nErrorCode) 
{
	CString strMsg;

	if (nErrorCode != 0) {
		strMsg.Format(IDS_DISCONNECTED, 
					  m_pMainWnd->GetHostAddr(), 
					  m_pMainWnd->GetHostPort());
		m_pMainWnd->AddMessage(strMsg);
		return;
	}
	
	CString strIP;
	UINT	uPort;
	if (!GetPeerName(strIP, uPort)) {
		TRACE0("fail to get peer information.\n");
		return;
	}
	
	// 	
	m_pMainWnd->SetConnected(TRUE);
	m_pMainWnd->CreateChatSocket();
	if (SendLoginInfo() <= 0) {
		TRACE0("fail to send log in information to server.\n");
		return;
	}
	
	// 更新显示
	strMsg.Format(IDS_SERVINFO, strIP, uPort, "已");
	m_pMainWnd->SetDlgItemText(IDC_SERVINFO_STATIC, strMsg);
	strMsg.Format(IDS_CONNECTED, strIP, uPort);
	m_pMainWnd->AddMessage(strMsg);
}

//--------------------------------------------------------------------------- 
//--------------------------------------------------------------------------- 
void CClientSocket::OnClose(int nErrorCode) 
{

}

//--------------------------------------------------------------------------- 
//--------------------------------------------------------------------------- 
void CClientSocket::OnReceive(int nErrorCode) 
{
	if (nErrorCode != 0) {
		return;
	}

	// 注销FD_READ事件
	if (!AsyncSelect(0)) {
		TRACE0("AsyncSelect error.\n");
		return;
	}
	// 读数据包类型
	WORD wPackType = 0;
	if (Receive(&wPackType, sizeof(wPackType), 0) != sizeof(wPackType))
	{
		TRACE0("Unable to receive package type!");
	}
	// 分析数据包类型
	switch (wPackType)
	{
	case PACKAGE_USERLIST: 
		OnReceiveUserList();
		break;
	case PACKAGE_USERADD: 
		OnReceiveUserAdd();
		break;
	case PACKAGE_USERDEL: 
		OnReceiveUserDel();
		break;
	case PACKAGE_MESSAGE: // 来自服务器的消息
		OnReceiveMessage();
		break;
	case PACKAGE_LOGOUT:
	case PACKAGE_SERVERCLOSE:
		OnOffline(wPackType);
		return; //注意, 既然已关闭套接字, 故直接返回
	default:
		break;
	}
	// 重新注册网络事件
	if (!AsyncSelect(FD_READ | FD_CLOSE | FD_CONNECT)) {
		TRACE0("AsyncSelect error.\n");
		return;
	}
}

void CClientSocket::OnReceiveUserList()
{
	int len = 0;
	// 读取列表长度
	if (Receive((void*)&len, sizeof(len), 0) != sizeof(len))
	{
		TRACE0("Unable to receive name list length.");
		return;
	}
	//
	if (len == 0) {
		return;
	}
	//
	USER_INFO* pArray = new USER_INFO[len];
	ASSERT(pArray != NULL);
	// receive user list
	if (Receive((void*)pArray, sizeof(USER_INFO) * len, 0) !=
		(int)sizeof(USER_INFO) * len) {
		TRACE0("Unable to receive name list data.");
		return;
	}
	// 将其添加到用户列表
	USER_INFO* pInfo = pArray;

	for (int i = 0; i < len; i++, pInfo++) {
		USER_INFO* p = new USER_INFO;
		memcpy((void*)p, (void*)pInfo, sizeof(USER_INFO));
		m_pMainWnd->AddUserInfo(p);
	}
	// 更新组合框的显示
	m_pMainWnd->AddNameList();
	
	//
	delete pArray;
}

void CClientSocket::OnReceiveUserAdd()
{
	USER_INFO* pInfo = new USER_INFO;
	ASSERT(pInfo != NULL);

	if (Receive((void*)pInfo, sizeof(USER_INFO), 0) 
		!= sizeof(USER_INFO)) {
		TRACE0("Unable to receive newly log in user data.\n");
		return;
	}
	// 将其添加到用户列表
	m_pMainWnd->AddUserInfo(pInfo);
	// 更新组合框显示
	m_pMainWnd->AddNameList();
	// 向消息框加入新消息
	CString strMsg;
	strMsg.Format(IDS_USERJOIN, pInfo->name, 
		inet_ntoa(*(in_addr*)&pInfo->addr), 
		pInfo->port);
	m_pMainWnd->AddMessage(strMsg);
}

void CClientSocket::OnReceiveUserDel()
{
	USER_INFO* pInfo = new USER_INFO;
	ASSERT(pInfo != NULL);
	
	if (Receive((void*)pInfo, sizeof(USER_INFO), 0) 
		!= sizeof(USER_INFO)) {
		TRACE0("Unable to receive log out user data.\n");
		return;
	}
	// remove user infomatioin from list
	if (!m_pMainWnd->DelUserInfo(pInfo)) {
		TRACE1("No such user %s.\n", pInfo->name);
		return;
	}
	// 更新组合框显示
	m_pMainWnd->AddNameList();
	// 向消息框增加消息
	CString strMsg;
	strMsg.Format(IDS_USERLEAVE, pInfo->name, 
			inet_ntoa(*(in_addr*)&pInfo->addr), 
			ntohs(pInfo->port));
	m_pMainWnd->AddMessage(strMsg);
	// 删除之
	delete pInfo;
}

void CClientSocket::OnReceiveMessage()
{
	char* pBuf = new char[0x1000]; // 4K byte
	ASSERT(pBuf != NULL);
	
	if (Receive((void*)pBuf, 0x1000, 0) <= 0)
	{
		TRACE0("fail to receive message from sever.\n");
		return;
	}

	// 得到对等方信息
	CString strDestAddr;
	UINT	uDestPort;
	if (!GetPeerName(strDestAddr, uDestPort)) {
		TRACE0("fail to get peer information.\n");
		return;
	}

	// 格式化消息文本
	CString strMsg;
	strMsg.Format(IDS_MESSAGE, strDestAddr, uDestPort, pBuf);
	m_pMainWnd->AddMessage(strMsg);
	
	delete [] pBuf;
}

void CClientSocket::OnOffline(WORD wType)
{
	// 格式化主机信息的Static
	CString strMsg;
	strMsg.Format(IDS_SERVINFO, "0.0.0.0", 0, "未");
	m_pMainWnd->SetDlgItemText(IDC_SERVINFO_STATIC, strMsg);
	// 添加离线原因的消息
	if (wType == PACKAGE_LOGOUT) {
		strMsg.LoadString(IDS_LOGOUT);
	} else if (wType == PACKAGE_SERVERCLOSE) {
		strMsg.Format(IDS_SERVERCLOSE, 
			m_pMainWnd->GetHostAddr(), 
			m_pMainWnd->GetHostPort());
	}

	m_pMainWnd->AddMessage(strMsg);

	// 关闭并设定状态变量的状态
	m_pMainWnd->ResetUserInfo();
	m_pMainWnd->SetClientSocket(NULL);
	m_pMainWnd->SetConnected(FALSE);
	Close();
	delete this;
}

int  CClientSocket::SendLoginInfo()
{
	const int LEN = sizeof(WORD) + sizeof(LOGIN_INFO);
	char pBuf[LEN];
	ASSERT(pBuf != NULL);
	
	// 填充pBuf
	*(WORD*)pBuf = PACKAGE_LOGIN;
	LOGIN_INFO* pLogin = (LOGIN_INFO*)(pBuf + sizeof(WORD));
	strcpy(pLogin->name, m_pMainWnd->GetUserName());
	strcpy(pLogin->password, m_pMainWnd->GetUserPassword());
	
	// 发送之
	return Send((void*)pBuf, LEN, 0);
}

⌨️ 快捷键说明

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