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

📄 datasocket.cpp

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

#include "stdafx.h"
#include "Server.h"
#include "MainFrm.h"
#include "..\\Common.h"
#include "DataSocket.h"
#include "ListenSocket.h"
#include "ServerDoc.h"
#include "ServerView.h"


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

/////////////////////////////////////////////////////////////////////////////
// CDataSocket

CDataSocket::CDataSocket(CAsyncSocket* pListenSock)
{
//	m_pMainWnd = ((CListenSocket*)pListenSock)->GetMainWnd();
	// 设定套接字选项
	LINGER linger;
	linger.l_onoff = 1;
	linger.l_linger = 5000; // 等待5秒
	SetSockOpt(SO_LINGER, (void*)&linger, sizeof(linger), SOL_SOCKET);

}

CDataSocket::~CDataSocket()
{
}


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

/////////////////////////////////////////////////////////////////////////////
// CDataSocket member functions

void CDataSocket::OnReceive(int nErrorCode) 
{
	if (nErrorCode != 0) {
		return;
	}
	
	// 查看数据包类型
	WORD type = 0;
	if (Receive((void*)&type, sizeof(type), 0) != sizeof(type)) {
		TRACE0("unable to receive package type info.");
		return;
	}
	
	switch (type) 
	{
	case PACKAGE_LOGIN: // login infomation
		OnReceiveLogin();
		break;
	case PACKAGE_LOGOUT:
		OnReceiveLogout();
		break;
	case PACKAGE_MESSAGE: // message send to server
		OnReceiveMessage();
		break;
	default:
		break;
	}	
}

void CDataSocket::OnReceiveLogin()
{
	LOGIN_INFO info;
	if (Receive((void*)&info, sizeof(info), 0) != sizeof(info)) {
		TRACE0("unable to receive user login infomation.");
		return;
	}
	// 你可以在这里检测用户名和密码的正确性, 为简单起见, 我们在这里跳过
	
	// 向其他用户发送该用户上线的消息
	SOCKADDR_IN addrIn;
	int	addrLen = sizeof(SOCKADDR_IN);

	if (!GetPeerName((SOCKADDR*)&addrIn, &addrLen)) {
		TRACE0("Unable to get peer name.\n");
		return;
	}

	USER_INFO userInfo;
	memcpy(userInfo.name, info.name, strlen(info.name) + 1);
	userInfo.port = addrIn.sin_port;
	userInfo.addr = addrIn.sin_addr.s_addr;
	
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CServerDoc* pDoc = (CServerDoc*)pFrame->GetActiveDocument();
	CServerView* pView = (CServerView*)pFrame->GetActiveView();

	// 更新显示消息
	CString strMsg;
	strMsg.Format(IDS_LOGIN, userInfo.name, 
		inet_ntoa(*(in_addr*)&userInfo.addr),
		ntohs(userInfo.port));
	pView->AppendMessage(strMsg);	

	// 向登录用户发送在线人员列表
	pDoc->SendUserListTo(userInfo, this);
	// 向所有用户发送该用户上线的消息
	pDoc->AlterUser(PACKAGE_USERADD, &userInfo, this);	
}

void CDataSocket::OnReceiveLogout()
{
	// 获取登出用户的信息
	USER_INFO info;

	if (Receive((void*)&info, sizeof(info), 0) != sizeof(info)) {
		TRACE0("unable to receive user logout infomation.\n");
		return;
	}
/*
	SOCKADDR_IN addrIn;
	int	addrLen = sizeof(SOCKADDR_IN);
	
	if (!GetPeerName((SOCKADDR*)&addrIn, &addrLen)) {
		TRACE0("Unable to get peer name.\n");
		return;
	}
*/	
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CServerDoc* pDoc = (CServerDoc*)pFrame->GetActiveDocument();
	CServerView* pView = (CServerView*)pFrame->GetActiveView();
/*
	USER_INFO* pUserInfo = pDoc->LookupInfo(addrIn.sin_addr.s_addr, addrIn.sin_port);
	if (pUserInfo == NULL) {
		return;
	}
*/
	// 发送确认用户退出的数据报
	const WORD type = PACKAGE_LOGOUT;
	if (Send((void*)&type, sizeof(type), 0) != sizeof(type)) {
		TRACE0("failed to send confirm message to the quitting user.\n");
		return;
	}
	// 关闭该套接字
	pDoc->GetListenSocket()->CloseDataSocket(this);
	
	// 向其他在线用户发消息, 告知有一用户离开
	pDoc->AlterUser(PACKAGE_USERDEL, &info, this);
	
	// 将该DataSocket加到死了的Socket链表
	// pDoc->AddDeadSock(this);
	
	// 更新显示
	CString strMsg;
	strMsg.Format(IDS_LOGOUT, info.name, 
		inet_ntoa(*(in_addr*)&info.addr),
		ntohs(info.port));
	pView->AppendMessage(strMsg);		
}

void CDataSocket::OnReceiveMessage()
{
	char* pBuf = new char[0x1000];
	ASSERT(pBuf != NULL);
	
	if (Receive((void*)pBuf, 0x1000, 0) <= 0) {
		TRACE0("failed to receive client message.");
		return;
	}
	
	// 显示消息
	SOCKADDR_IN addrIn;
	int	addrLen = sizeof(SOCKADDR_IN);
	
	if (!GetPeerName((SOCKADDR*)&addrIn, &addrLen)) {
		TRACE0("Unable to get peer name.\n");
		return;
	}

	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CServerDoc* pDoc = (CServerDoc*)pFrame->GetActiveDocument();
	CServerView* pView = (CServerView*)pFrame->GetActiveView();
	
	USER_INFO* pInfo = pDoc->LookupInfo(addrIn.sin_addr.s_addr, addrIn.sin_port);
	CString strMsg;
	strMsg.Format(IDS_MESSAGE, pInfo->name, 
		pBuf, inet_ntoa(*(in_addr*)&pInfo->addr));
	pView->AppendMessage(strMsg);
}

void CDataSocket::OnClose(int nErrorCode) 
{	
	//	CAsyncSocket::OnClose(nErrorCode);
	Close();	
}

⌨️ 快捷键说明

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