📄 serverdoc.cpp
字号:
// ServerDoc.cpp : implementation of the CServerDoc class
#include "stdafx.h"
#include "Server.h"
#include "MainFrm.h"
#include "ServerDoc.h"
#include "Serverview.h"
#include "ServInfoDlg.h"
#include "ListenSocket.h"
#include "DataSocket.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CServerDoc
IMPLEMENT_DYNCREATE(CServerDoc, CDocument)
BEGIN_MESSAGE_MAP(CServerDoc, CDocument)
//{{AFX_MSG_MAP(CServerDoc)
ON_COMMAND(ID_NETWORK_START, OnNetworkStart)
ON_COMMAND(ID_NETWORK_TERMINATE, OnNetworkTerminate)
ON_COMMAND(ID_APP_EXIT, OnAppExit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerDoc construction/destruction
CServerDoc::CServerDoc()
{
// TODO: add one-time construction code here
m_pListenSocket = NULL;
m_bStarted = FALSE;
}
CServerDoc::~CServerDoc()
{
}
BOOL CServerDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CServerDoc serialization
void CServerDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CServerDoc diagnostics
#ifdef _DEBUG
void CServerDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CServerDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CServerDoc commands
// 向pSocket发送用户列表
void CServerDoc::SendUserListTo(USER_INFO& userInfo, CDataSocket* pSocket)
{
int cnt = m_lstUserInfo.GetCount();
int total = sizeof(WORD) + sizeof(cnt) + sizeof(USER_INFO) * cnt;
char* buf = new char[total];
// 拷贝欲发送的数据到缓冲区
*(WORD*)buf = PACKAGE_USERLIST;
*(int*)(buf + sizeof(WORD)) = cnt;
POSITION pos = m_lstUserInfo.GetHeadPosition();
USER_INFO* p = (USER_INFO*)(buf + sizeof(cnt) + sizeof(WORD));
for (int i = 0; i < cnt; i++, p++) {
USER_INFO& info = m_lstUserInfo.GetNext(pos);
memcpy((void*)p, (void*)&info, sizeof(USER_INFO));
}
// 发送数据
if (pSocket->Send((void*)buf, total, 0) <= 0) {
TRACE0("failed to send namelist to user.");
return;
}
// 显示消息
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CServerView* pView = (CServerView*)pFrame->GetActiveView();
CString strMsg;
strMsg.Format(IDS_SENDNAMELIST, cnt, userInfo.name,
inet_ntoa(*(in_addr*)&userInfo.addr),
htons(userInfo.port));
pView->AppendMessage(strMsg);
delete [] buf;
}
// 查找USER_INFO消息
USER_INFO* CServerDoc::LookupInfo(UINT IP, UINT port)
{
POSITION pos = m_lstUserInfo.GetHeadPosition();
//
for (int i = 0; i < m_lstUserInfo.GetCount(); i++)
{
USER_INFO& info = m_lstUserInfo.GetNext(pos);
if (info.addr == IP && info.port == port) {
return &info;
}
}
//
return NULL;
}
// 启动服务器
void CServerDoc::OnNetworkStart()
{
CServInfoDlg dlg;
if (dlg.DoModal() == IDCANCEL) {
return;
}
if (!m_bStarted) {
if (m_pListenSocket != NULL) {
delete m_pListenSocket;
}
m_pListenSocket = new CListenSocket();
}
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CServerView* pView = (CServerView*)pFrame->GetActiveView();
CString strMsg;
// 创建
if (!m_pListenSocket->Create(dlg.m_uPort, SOCK_STREAM,
FD_ACCEPT,
dlg.m_strIP))
{
TRACE0("Unable to create listen socket.\n");
delete m_pListenSocket;
m_pListenSocket = NULL;
strMsg.Format(IDS_CREATE_LISTEN_SOCKET_FAILED, dlg.m_strIP, dlg.m_uPort);
pView->AppendMessage(strMsg);
return;
}
// 监听
if (!m_pListenSocket->Listen(5)) {
TRACE0("Unable to listen address.\n");
m_pListenSocket->Close();
delete m_pListenSocket;
m_pListenSocket = NULL;
strMsg.Format(IDS_LISTEN_FAILED, dlg.m_strIP, dlg.m_uPort);
pView->AppendMessage(strMsg);
return;
}
m_bStarted = TRUE;
strMsg.Format(IDS_STARTUP, dlg.m_strIP, dlg.m_uPort);
pView->AppendMessage(strMsg);
}
// 终止服务器
void CServerDoc::OnNetworkTerminate()
{
if (!m_bStarted) {
return;
}
// 清除用户信息
m_lstUserInfo.RemoveAll();
// 向每个套接字发送服务器关闭信息
WORD type = PACKAGE_SERVERCLOSE;
m_pListenSocket->SendPackageToAll((char*)&type,
sizeof(type),
NULL);
// 重新计时
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CServerView* pView = (CServerView*)pFrame->GetActiveView();
// 关闭数据套接字
m_pListenSocket->CloseAllSocks();
// 关闭监听套接字
m_pListenSocket->Close();
// 更新显示
CString strMsg;
strMsg.LoadString(IDS_LISTENSOCKETCLOSED);
pView->AppendMessage(strMsg);
m_bStarted = FALSE;
}
// 退出应用程序
void CServerDoc::OnAppExit()
{
if (m_bStarted) {
OnNetworkTerminate();
}
PostQuitMessage(EXIT_SUCCESS);
}
// 关闭套接字pSock
void CServerDoc::CloseDataSocket(CDataSocket* pSock)
{
m_pListenSocket->CloseDataSocket(pSock);
}
// 以type类型, *pInfo为内容的消息通知除pFrom外的套接字
BOOL CServerDoc::AlterUser(WORD type, USER_INFO* pInfo, CDataSocket* pFrom)
{
CString strMsg;
CServerView* pView = (CServerView*)(((CMainFrame*)AfxGetMainWnd())->GetActiveView());
if (type == PACKAGE_USERADD) {
AddUserInfo(*pInfo);
}
else if (type == PACKAGE_USERDEL) {
RemoveUserInfo(*pInfo);
}
else {
return FALSE;
}
// 填充消息结构
const int bufLen = sizeof(WORD) + sizeof(USER_INFO);
char buffer[bufLen];
*(WORD*)buffer = type;
memcpy((void*)&buffer[sizeof(WORD)], (void*)pInfo, sizeof(USER_INFO));
// 向每个DataSocket发送消息
return m_pListenSocket->SendPackageToAll(buffer, bufLen, pFrom);
}
// 移去pInfo
void CServerDoc::RemoveUserInfo(USER_INFO& pInfo)
{
POSITION pos = m_lstUserInfo.GetHeadPosition();
//
for (int i = 0; i < m_lstUserInfo.GetCount(); i++)
{
POSITION temp = pos;
USER_INFO& p = m_lstUserInfo.GetNext(pos);
//
if (strcmp(pInfo.name, p.name) == 0 &&
pInfo.addr == p.addr &&
pInfo.port == p.port) {
m_lstUserInfo.RemoveAt(temp);
return;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -