Files
HLStock/StockServer/ServerSocket.cpp
2013-07-20 23:20:35 +00:00

444 lines
11 KiB
C++

#include "stdafx.h"
#include "StockServer.h"
#include "ServerSocket.h"
#include "ClientSocket.h"
#include "..\\Common\\ComData.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CServerSocket
CServerSocket::CServerSocket(CMainFrame* pMainFrame)
{
ASSERT(pMainFrame);
m_pMainFrame = pMainFrame;
m_nMaxClients = -1;
}
CServerSocket::~CServerSocket()
{
CloseClients();
UpdateClientsList();
Close();
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CServerSocket, CSocket)
//{{AFX_MSG_MAP(CServerSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CListeningSocket member functions
CPtrList* CServerSocket::GetClientsList()
{
if (m_ClientstList.IsEmpty())
return NULL;
return &m_ClientstList;
}
int CServerSocket::GetClientsConnectedCount()
{
return m_ClientstList.GetCount();
}
int CServerSocket::GetTotalMessagesCount()
{
int nMessageCount = 0;
int nCount = m_ClientstList.GetCount();
for (int i = 0; i < nCount; i++) {
sClientComInfos* pClientCom = (sClientComInfos*)m_ClientstList.GetAt(m_ClientstList.FindIndex(i));
ASSERT(pClientCom);
nMessageCount += pClientCom->szMessagesList.GetCount();
}
return nMessageCount;
}
BOOL CServerSocket::BeginListening(UINT uPort, int nMaxClients)
{
m_nMaxClients = nMaxClients;
if(!m_ClientstList.IsEmpty())
CloseClients();
if (!Create(uPort))
return FALSE;
if (!Listen())
return FALSE;
return TRUE;
}
void CServerSocket::OnAccept(int nErrorCode)
{
CSocket::OnAccept(nErrorCode);
ProcessAccept();
}
//when got a connection message from a client
void CServerSocket::ProcessAccept()
{
CClientSocket* pClientSocket = new CClientSocket(this);
ASSERT(pClientSocket);
if (!Accept(*pClientSocket)) {
delete pClientSocket;
return;
}
pClientSocket->Init();
if (m_nMaxClients != -1) {
if (m_nMaxClients <= m_ClientstList.GetCount()) {
try {
//send the connection confirmation to the client,add to the list - yh
CComData ComData;
ComData.m_ComDataType = CComData::COM_CLOSE;
ComData.m_FromID = CString((LPCTSTR)IDS_COM_SERVER);
ComData.m_StringBody = "서버의 최대접속수를 넘었습니다.";
pClientSocket->SendCom(&ComData);
delete pClientSocket;
m_pMainFrame->AddMessage( ComData.m_FromID, ComData.m_StringBody );
return;
}
catch(CFileException* e){
TCHAR csError[CHAR_BUFFER_SIZE];
e->GetErrorMessage(csError, CHAR_BUFFER_SIZE);
AfxMessageBox(csError);
}
}
}
try {
//send the connection confirmation to the client,add to the list - yh
CComData ComData;
ComData.m_ComDataType = CComData::COM_SIGN_IN;
ComData.m_FromID = CString((LPCTSTR)IDS_COM_SERVER);
pClientSocket->SendCom(&ComData);
}
catch(CFileException* e){
TCHAR csError[CHAR_BUFFER_SIZE];
e->GetErrorMessage(csError, CHAR_BUFFER_SIZE);
AfxMessageBox(csError);
}
CString szIPAddress;
UINT uPort;
pClientSocket->GetPeerName(szIPAddress, uPort);
sClientComInfos* pClientCom = new sClientComInfos;
ASSERT(pClientCom);
pClientCom->pSocket = (DWORD)pClientSocket;
pClientCom->strID = "";
pClientCom->szIPAddress = szIPAddress;
pClientCom->uPort = uPort;
pClientCom->TimeStarted = CTime::GetCurrentTime();
if(m_ClientstList.IsEmpty()){
m_ClientstList.AddHead(pClientCom);
}
else{
m_ClientstList.AddTail(pClientCom);
}
}
void CServerSocket::ProcessClientCom(CClientSocket* pClientSocket)
{
ASSERT(pClientSocket);
try {
CComData ComData;
pClientSocket->ReceiveCom(&ComData);
if(ComData.m_ComDataType == CComData::COM_SIGN_IN) {
if(IsThisLoginBeingUsed(pClientSocket, &ComData)) {
try {
//send the connection confirmation to the client,add to the list - yh
ComData.Initialize();
ComData.m_ComDataType = CComData::COM_CLOSE;
ComData.m_FromID = CString((LPCTSTR)IDS_COM_SERVER);
ComData.m_StringBody = "접속제한 수를 넘었습니다.";
pClientSocket->SendCom(&ComData);
}
catch(CFileException* e) {
TCHAR csError[CHAR_BUFFER_SIZE];
e->GetErrorMessage(csError, CHAR_BUFFER_SIZE);
AfxMessageBox(csError);
}
RemoveClient(pClientSocket);
return;
}
SendSignChange( pClientSocket, ComData.m_StringBody );
UpdateClientsList();
m_pMainFrame->AddMessage(ComData.m_StringBody, "Client Sign in." );
}
else if(ComData.m_ComDataType == CComData::COM_SIGN_OUT) {
RemoveClient(pClientSocket);
UpdateClientsList();
m_pMainFrame->AddMessage(ComData.m_FromID, "Client Sign out." );
}
else if(ComData.m_ComDataType == CComData::COM_MESSAGE) {
m_pMainFrame->AddMessage(ComData.m_FromID, ComData.m_StringBody );
UpdateClientsInfo(&ComData, pClientSocket);
}
}
catch(CFileException* e) {
TCHAR csError[CHAR_BUFFER_SIZE];
e->GetErrorMessage(csError, CHAR_BUFFER_SIZE);
AfxMessageBox(csError);
}
}
void CServerSocket::SendSignChange(CClientSocket* pClientSocket, CString strNewId)
{
int nCount = m_ClientstList.GetCount();
for (int i = 0; i < nCount; i++) {
sClientComInfos* pClientCom = (sClientComInfos*)m_ClientstList.GetAt(m_ClientstList.FindIndex(i));
ASSERT(pClientCom);
CClientSocket* pClientSocketTmp = (CClientSocket*)pClientCom->pSocket;
ASSERT(pClientSocketTmp);
if(pClientSocket == pClientSocketTmp)
{
pClientCom->strID = strNewId; // 서버에서 클라이언트 리스트의 접속ID확정함.
CComData ComData;
ComData.m_ComDataType = CComData::COM_SIGN_CHANGE;
ComData.m_FromID = CString((LPCTSTR)IDS_COM_SERVER);
ComData.m_StringBody = strNewId;
pClientSocket->SendCom(&ComData);
return ;
}
}
}
BOOL CServerSocket::CheckAlive(CClientSocket* pClientSocket, int nCheck)
{
CComData ComData;
ComData.m_ComDataType = CComData::COM_CHECKALIVE;
ComData.m_FromID = CString((LPCTSTR)IDS_COM_SERVER);
while( nCheck-- )
{
if( pClientSocket->SendCom(&ComData) == FALSE )
{
RemoveClient(pClientSocket);
return FALSE;
}
}
return TRUE;
}
BOOL CServerSocket::IsThisLoginBeingUsed(CClientSocket* pClientSocket, CComData* pComData)
{
ASSERT(pClientSocket);
CString strCheckID = pComData->m_FromID;
if(strCheckID == CString((LPCTSTR)IDS_COM_SERVER))
return TRUE; // this name is used by server only!
if(m_ClientstList.IsEmpty()) return TRUE;
int nCount = m_ClientstList.GetCount();
int nCheckCount = 0;
while(nCheckCount++ < 2) { // 같은ID일경우 2개까지만 허용함.
BOOL bStop = TRUE;
for (int i = 0; i < nCount; i++) {
sClientComInfos* pClientCom = (sClientComInfos*)m_ClientstList.GetAt(m_ClientstList.FindIndex(i));
ASSERT(pClientCom);
CClientSocket* pClientSocketTmp = (CClientSocket*)pClientCom->pSocket;
ASSERT(pClientSocketTmp);
if(strCheckID == pClientCom->strID &&
pClientSocket != pClientSocketTmp)
{
if( !CheckAlive(pClientSocketTmp) )
{
pComData->m_StringBody = strCheckID;
return FALSE;
}
strCheckID.Format("%s(%dth)", pComData->m_FromID, nCheckCount);
bStop = FALSE;
break;
}
}
if( bStop ) {
pComData->m_StringBody = strCheckID;
return FALSE;
}
}
return TRUE;
}
void CServerSocket::UpdateClientsList()
{
m_pMainFrame->UpdateClientsList(&m_ClientstList);
}
void CServerSocket::UpdateClientsInfo(CComData* pComData, CClientSocket* pClientSocket)
{
ASSERT(pComData);
int nCount = m_ClientstList.GetCount();
for (int i = 0; i < nCount; i++) {
sClientComInfos* pClientCom = (sClientComInfos*)m_ClientstList.GetAt(m_ClientstList.FindIndex(i));
ASSERT(pClientCom);
CClientSocket* pClientSocketTmp = (CClientSocket*)pClientCom->pSocket;
ASSERT(pClientSocketTmp);
if (pClientSocket == pClientSocketTmp) {
CString szBuf;
szBuf.Format("%s;%s", GlobalHelper::GetLocalTime(), pComData->m_StringBody);
if (pClientCom->szMessagesList.IsEmpty())
pClientCom->szMessagesList.AddHead(szBuf);
else
pClientCom->szMessagesList.AddTail(szBuf);
return;
}
}
}
void CServerSocket::RemoveClient(CClientSocket* pClientSocket)
{
ASSERT(pClientSocket);
int nCount = m_ClientstList.GetCount();
for (int i = 0; i < nCount; i++) {
sClientComInfos* pClientCom = (sClientComInfos*)m_ClientstList.GetAt(m_ClientstList.FindIndex(i));
ASSERT(pClientCom);
CClientSocket* pClientSocketTmp = (CClientSocket*)pClientCom->pSocket;
ASSERT(pClientSocketTmp);
if(pClientSocket == pClientSocketTmp) {
m_ClientstList.RemoveAt(m_ClientstList.FindIndex(i));
pClientSocketTmp->Close();
delete pClientSocketTmp;
pClientSocketTmp = NULL;
pClientCom->szMessagesList.RemoveAll();
delete pClientCom;
pClientCom = NULL;
return;
}
}
}
void CServerSocket::CloseClients()
{
int nCount = m_ClientstList.GetCount();
for (int i = 0; i < nCount; i++) {
sClientComInfos* pClientCom = (sClientComInfos*)m_ClientstList.GetAt(m_ClientstList.FindIndex(i));
ASSERT(pClientCom);
CClientSocket* pClientSocketTmp = (CClientSocket*)pClientCom->pSocket;
ASSERT(pClientSocketTmp);
try {
//send the connection confirmation to the client,add to the list - yh
CComData ComData;
ComData.m_ComDataType = CComData::COM_CLOSE;
ComData.m_FromID = CString((LPCTSTR)IDS_COM_SERVER);
ComData.m_StringBody = "연결종료합니다.";
pClientSocketTmp->SendCom(&ComData);
}
catch(CFileException* e) {
TCHAR csError[CHAR_BUFFER_SIZE];
e->GetErrorMessage(csError, CHAR_BUFFER_SIZE);
AfxMessageBox(csError);
}
pClientSocketTmp->Close();
delete pClientSocketTmp;
pClientSocketTmp = NULL;
m_pMainFrame->AddMessage(pClientCom->strID, "연결종료합니다.");
pClientCom->szMessagesList.RemoveAll();
delete pClientCom;
pClientCom = NULL;
}
m_ClientstList.RemoveAll();
}
void CServerSocket::SendMessageTo(CString szClient, CString szMessage)
{
/* int nCount = m_ClientstList.GetCount();
for (int i = 0; i < nCount; i++) {
sClientComInfos* pClientCom = (sClientComInfos*)m_ClientstList.GetAt(m_ClientstList.FindIndex(i));
ASSERT(pClientCom);
CComData* pComDataTmp = (CComData*)&pClientCom->ComData;
ASSERT(pComDataTmp);
CClientSocket* pClientSocketTmp = (CClientSocket*)pComDataTmp->pSocket;
ASSERT(pClientSocketTmp);
if (pComDataTmp->szFrom == szClient) {
try {
//send the connection confirmation to the client,add to the list - yh
CComData ComDataTmp;
ComDataTmp.szFrom = CString((LPCTSTR)IDS_COM_SERVER);
ComDataTmp.uSignIcon = SERVER_ICON;
ComDataTmp.szMessage = szMessage;
ComDataTmp.uMessage = CComData::COM_PRIVATE_MESSAGE;
pClientSocketTmp->SendCom(&ComDataTmp);
}
catch(CFileException* e) {
TCHAR csError[CHAR_BUFFER_SIZE];
e->GetErrorMessage(csError, CHAR_BUFFER_SIZE);
AfxMessageBox(csError);
}
return;
}
}
*/
}