📄 chatserverdoc.cpp
字号:
// ChatServerDoc.cpp : implementation of the CChatServerDoc class
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
// ChatServerDoc.cpp : implementation of the CChatServerDoc class
//
#include "stdafx.h"
#include "ChatServer.h"
#include "ChatServerDoc.h"
#include "SrvrItem.h"
#include "MainFrm.h"
#include "ChatView.h"
#include "LeftView.h"
#include "ChattersListView.h"
#include "PortDlg.h"
#include "Msg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc
IMPLEMENT_DYNCREATE(CChatServerDoc, COleServerDoc)
BEGIN_MESSAGE_MAP(CChatServerDoc, COleServerDoc)
//{{AFX_MSG_MAP(CChatServerDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc construction/destruction
CChatServerDoc::CChatServerDoc()
{
// Use OLE compound files
EnableCompoundFile();
m_pSocket = NULL;
m_pChattersList.RemoveAll();
m_chattersListPtr.RemoveAll();
m_msgPtr.RemoveAll();
m_stdCF.cbSize = sizeof(CHARFORMAT);
m_stdCF.dwMask = 0;
m_stdCF.dwEffects = 0;
m_stdCF.yHeight = 0;
m_stdCF.yOffset = 0;
m_stdCF.crTextColor = RGB(255,0,0);
m_stdCF.bCharSet = 0;
m_stdCF.bPitchAndFamily = 0;
strcpy(m_stdCF.szFaceName, "Arial");
}
CChatServerDoc::~CChatServerDoc()
{
}
BOOL CChatServerDoc::OnNewDocument()
{
if (!COleServerDoc::OnNewDocument())
return FALSE;
CPortDlg Dialog;
if (Dialog.DoModal() == IDOK)
{
m_pSocket = new CListeningSocket(this);
if (m_pSocket->Create(Dialog.m_nPort+1500)) // 700
{
if (m_pSocket->Listen())
return TRUE;
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc server implementation
COleServerItem* CChatServerDoc::OnGetEmbeddedItem()
{
// OnGetEmbeddedItem is called by the framework to get the COleServerItem
// that is associated with the document. It is only called when necessary.
CChatServerSrvrItem* pItem = new CChatServerSrvrItem(this);
ASSERT_VALID(pItem);
return pItem;
}
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc serialization
void CChatServerDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// CEditView contains an edit control which handles all serialization
((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);
}
}
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc diagnostics
#ifdef _DEBUG
void CChatServerDoc::AssertValid() const
{
COleServerDoc::AssertValid();
}
void CChatServerDoc::Dump(CDumpContext& dc) const
{
COleServerDoc::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CChatServerDoc commands
void CChatServerDoc::DeleteContents()
{
if(m_pSocket == (CListeningSocket*)NULL)
return;
delete m_pSocket;
m_pSocket = NULL;
CString temp;
if (temp.LoadString(IDS_SERVERSHUTDOWN))
{
// m_msgList.AddTail(temp);
}
CMsg* pMsg = new CMsg();
pMsg->Init();
pMsg->m_msgList.AddTail(temp);
pMsg->code = NORMAL_MESSAGE;
pMsg->m_bClose = TRUE;
while(!m_connectionList.IsEmpty())
{
CClientSocket* pSocket = (CClientSocket*)m_connectionList.RemoveHead();
SendMsg(pSocket, pMsg);
if (!pSocket->IsAborted())
{
pSocket->ShutDown();
BYTE Buffer[50];
while (pSocket->Receive(Buffer,50) > 0);
delete pSocket;
}
}
CDocument::DeleteContents();
}
void CChatServerDoc::SendUpdatedList(CClientSocket* pSocket)
{
POSITION pos;
CMsg* pMsg = new CMsg();
pMsg->Init();
for(pos = m_pChattersList.GetHeadPosition(); pos != NULL;)
{
CString tempName = m_pChattersList.GetNext(pos);
pMsg->m_chattersList.AddTail(tempName);
}
pMsg->code = SENDING_CHATTERS_LIST;
for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos);
if (pSocket != NULL)
SendMsg(pSocket, pMsg);
}
}
void CChatServerDoc::UpdateClients(int nCode)
{
for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos);
CMsg* pMsg = AssembleMsg(pSocket, nCode);
if (pMsg != NULL)
{
pMsg->code = nCode;
SendMsg(pSocket, pMsg);
}
}
}
void CChatServerDoc::ProcessPendingAccept()
{
CClientSocket* pSocket = new CClientSocket(this);
if (!m_pSocket->Accept(*pSocket))
{
delete pSocket;
}
else
{
pSocket->Init();
CMsg* msg = new CMsg();
pSocket->ReceiveMsg(msg);
CString cNickName = msg->m_strText;
if(DuplicateName(cNickName))
{
CMsg* mmsg = new CMsg;
mmsg->Init();
mmsg->code = DUPLICATE_NICKNAME;
CString string;
string.LoadString(IDS_NICKINUSE);
mmsg->m_strText = string;
SendMsg(pSocket , mmsg);
pSocket->ShutDown();
BYTE Buffer[50];
while (pSocket->Receive(Buffer,50) > 0);
delete pSocket;
}
else
{
pSocket->m_ChattersName = cNickName;
UpdateChattersNames(cNickName, pSocket);
m_connectionList.AddTail(pSocket);
UpdateConnections();
SendUpdatedList(pSocket);
UpdateChattersList(cNickName, pSocket);
}
}
}
void CChatServerDoc::ProcessPendingRead(CClientSocket* pSocket)
{
CMsg* pMsg;
do
{
pMsg = ReadMsg(pSocket);
if((pMsg->code == PRIVATE_MESSAGE) || (pMsg->code == KICK_USER))
{
CClientSocket* cSock = (CClientSocket*)CAsyncSocket::FromHandle(pMsg->m_hSocket);
SendMsg(cSock , pMsg);
}
if(pMsg->m_bClose)
{
CString cNickName = pSocket->m_ChattersName;
UpdateClients(LEAVING_CHAT);
DeleteChatter(pMsg , cNickName);
CloseSocket(pSocket);
SendUpdatedList(pSocket);
break;
}
else
UpdateClients(NORMAL_MESSAGE);
}
while (!pSocket->m_pArchiveIn->IsBufferEmpty());
}
CMsg* CChatServerDoc::AssembleMsg(CClientSocket* pSocket , int nCode)
{
static CMsg msg;
msg.Init();
if (pSocket->m_nMsgCount >= m_msgPtr.GetCount())
return NULL;
CString tempPrev = _T("");
for (POSITION pos = m_msgPtr.FindIndex(pSocket->m_nMsgCount); pos != NULL;)
{
CMsg* msg1 = (CMsg*)m_msgPtr.GetNext(pos);
CString temp = msg1->m_strText;
if(tempPrev != temp)
{
msg.m_msgList.AddTail(temp);
msg.m_dwMask = msg1->m_dwMask;
msg.m_dwEffects = msg1->m_dwEffects;
msg.m_yHeight = msg1->m_yHeight;
msg.m_yOffset = msg1->m_yOffset;
msg.m_crTextColor = msg1->m_crTextColor;
msg.m_bCharSet = msg1->m_bCharSet;
msg.m_bPitchAndFamily = msg1->m_bPitchAndFamily;
msg.m_szFaceName = msg1->m_szFaceName;
msg.code = nCode;
}
tempPrev = temp;
}
pSocket->m_nMsgCount = m_msgPtr.GetCount();
UpdateMessages();
return &msg;
}
CMsg* CChatServerDoc::ReadMsg(CClientSocket* pSocket)
{
static CMsg msg;
TRY
{
pSocket->ReceiveMsg(&msg);
if(msg.code == SENDING_NICKNAME)
{
UpdateChattersList(msg.m_strText , pSocket);
}
if(msg.code == NORMAL_MESSAGE)
{
CHARFORMAT2 cf;
cf.cbSize = sizeof(CHARFORMAT2);
cf.dwMask = msg.m_dwMask;
cf.dwEffects = msg.m_dwEffects;
cf.yHeight = msg.m_yHeight;
cf.yOffset = msg.m_yOffset;
cf.crTextColor = msg.m_crTextColor;
cf.bCharSet = msg.m_bCharSet;
cf.bPitchAndFamily = msg.m_bPitchAndFamily;
strcpy(cf.szFaceName, msg.m_szFaceName);
Message(msg.m_strText , cf);
m_msgList.AddTail(msg.m_strText);
m_msgPtr.AddTail(&msg);
}
}
CATCH(CFileException, e)
{
CString strTemp;
if (strTemp.LoadString(IDS_READERROR))
Message(strTemp , m_stdCF);
msg.m_bClose = TRUE;
pSocket->Abort();
}
END_CATCH
return &msg;
}
void CChatServerDoc::SendMsg(CClientSocket* pSocket, CMsg* pMsg)
{
TRY
{
pSocket->SendMsg(pMsg);
}
CATCH(CFileException, e)
{
pSocket->Abort();
CString strTemp;
if (strTemp.LoadString(IDS_SENDERROR))
Message(strTemp, m_stdCF);
}
END_CATCH
}
void CChatServerDoc::CloseSocket(CClientSocket* pSocket)
{
pSocket->Close();
POSITION pos,temp;
for(pos = m_connectionList.GetHeadPosition(); pos != NULL;)
{
temp = pos;
CClientSocket* pSock = (CClientSocket*)m_connectionList.GetNext(pos);
if (pSock == pSocket)
{
m_connectionList.RemoveAt(temp);
break;
}
}
UpdateConnections();
delete pSocket;
if(m_connectionList.GetCount() == 0)
{
m_msgList.RemoveAll();
m_pChattersList.RemoveAll();
}
}
void CChatServerDoc::Message(LPCTSTR lpszMessage, CHARFORMAT cf)
{
for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
{
CView* pView = GetNextView(pos);
CChatView* pChatView = DYNAMIC_DOWNCAST(CChatView, pView);
if (pChatView != NULL)
pChatView->message(lpszMessage, cf);
}
}
/////////////////////////////////////////////////////////////////////////////
// CServerDoc Handlers
void CChatServerDoc::UpdateMessages()
{
CMainFrame* cwnd = (CMainFrame*)AfxGetMainWnd();
if(cwnd != NULL)
cwnd->m_MessageCount = m_msgList.GetCount();
}
void CChatServerDoc::UpdateConnections()
{
CMainFrame* cwnd = (CMainFrame*)AfxGetMainWnd();
cwnd->m_ConnectionCount = m_connectionList.GetCount();
}
void CChatServerDoc::UpdateChattersList(CString sName, CClientSocket* pSocket)
{
CAsyncSocket* cSocket = (CAsyncSocket*)pSocket;
CString sIPAddress;
UINT iPort;
cSocket->GetPeerName(sIPAddress , iPort);
for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
{
CView* pView = GetNextView(pos);
CChattersListView* pChattersListView = DYNAMIC_DOWNCAST(CChattersListView, pView);
if (pChattersListView != NULL)
pChattersListView->UpdateChatters(sName , sIPAddress , iPort);
}
}
void CChatServerDoc::DeleteChatter(CMsg* pMsg, CString sName)
{
POSITION pos;
for(pos=GetFirstViewPosition();pos!=NULL;)
{
CView* pView = GetNextView(pos);
CChattersListView* pChattersListView = DYNAMIC_DOWNCAST(CChattersListView, pView);
if (pChattersListView != NULL)
pChattersListView->DeleteChatter(sName);
}
POSITION temp;
for(pos = m_pChattersList.GetHeadPosition(); pos != NULL;)
{
temp = pos;
CString tempName = (CString)m_pChattersList.GetNext(pos);
// Strip out Socket from Name
tempName = tempName.Left(tempName.Find(":",0));
if(sName == tempName)
m_pChattersList.RemoveAt(temp);
}
}
void CChatServerDoc::UpdateChattersNames(CString sName , CClientSocket* pSocket)
{
CString sock, string;
sock.Format("%d" , pSocket->m_hSocket);
sName += "::" + sock;
m_pChattersList.AddTail(sName);
}
BOOL CChatServerDoc::DuplicateName(CString sNickName)
{
return (m_pChattersList.Find(sNickName, NULL) == NULL ? FALSE : TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -