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

📄 serverprogramdlg.cpp

📁 Client 和Server 配套的网络连接程序。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ServerProgramDlg.cpp : implementation file
// Copyright (c) 2002
// 
// Written by: Jeff Miles
// Email: jeffmiles99@hotmail.com
//
// Thank you to both Adam Clauss for his IniFile class, and
// Chris Maunder and Warren Young for their System Tray work.
//
// This program is the Server portion to a complete
// Client/Server framework.  Feel free to use this framework
// as the basis for your network application. If you do use
// this framework, please let me know via e-mail.
//
// Since this program has not been extensively tested, expect bugs.
// Please e-mail me any suggestions or bugs that you find, or better
// yet, any modifications that you have made that adds to this programs
// functionality or efficiency.
//
// ***THIS VERSION FIXED THE FOLLOWING TWO BUGS IN VERSION 1.0***
// Known Bug: The Server Program does not compile in Debug mode.
//            Use Release mode instead.
//
// Known Bug: The Server Program's Exit button does not function correctly.
//            Use the "Shut Down Server" button instead.
//


#include "stdafx.h"
#include "ServerProgram.h"
#include "ServerProgramDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CServerProgramDlg dialog

//This block of code is necessary for the System Tray functionality
const char* kpcTrayNotificationMsg_ = "Server tray notification";
CServerProgramDlg::CServerProgramDlg(CWnd* pParent) : 
CDialog(CServerProgramDlg::IDD, pParent),
bMinimized_(false),
pTrayIcon_(0),
nTrayNotificationMsg_(RegisterWindowMessage(kpcTrayNotificationMsg_))

{
	//{{AFX_DATA_INIT(CServerProgramDlg)
	m_nTotalUsers = _T("");
	m_nUsersOnline = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CServerProgramDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CServerProgramDlg)
	DDX_Control(pDX, IDC_USERS, m_Users);
	DDX_Text(pDX, IDC_TOTALUSERS, m_nTotalUsers);
	DDX_Text(pDX, IDC_ONLINEUSERS, m_nUsersOnline);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CServerProgramDlg, CDialog)
	//{{AFX_MSG_MAP(CServerProgramDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_SETTINGS, OnSettings)
	ON_BN_CLICKED(IDC_VIEWLOG, OnViewlog)
	ON_BN_CLICKED(IDOK, OnExitServer)
	ON_BN_CLICKED(IDC_VIEWUSERS, OnViewusers)
	ON_WM_TIMER()
	ON_WM_CLOSE()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_RECEIVE_MESSAGE,OnReceiveMessage)
	ON_MESSAGE(WM_USER_EXIT,OnUserDisconnect)
	ON_MESSAGE(WM_USER_CONNECT,OnUserConnect)
	ON_COMMAND(IDC_ST_RESTORE, OnSTRestore)
	ON_COMMAND(IDC_ST_EXIT, OnSTExit)
END_MESSAGE_MAP()

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// The following block is necessary for the System Tray functionality
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

//// SetupTrayIcon /////////////////////////////////////////////////////
// If we're minimized, create an icon in the systray.  Otherwise, remove
// the icon, if one is present.

void CServerProgramDlg::SetupTrayIcon()
{
	if (bMinimized_ && (pTrayIcon_ == 0)) {
		pTrayIcon_ = new CSystemTray;
		pTrayIcon_->Create(0, nTrayNotificationMsg_, "Total Users Connected: " + m_nTotalUsers + " Users Currently Online: " + m_nUsersOnline,
							m_hIcon, IDR_SYSTRAY_MENU);
	}
	else {
		delete pTrayIcon_;
		pTrayIcon_ = 0;
	}
}

//// SetupTaskBarButton ////////////////////////////////////////////////
// Show or hide the taskbar button for this app, depending on whether
// we're minimized right now or not.

void CServerProgramDlg::SetupTaskBarButton()
{
	// Show or hide this window appropriately
	if (bMinimized_) {
		ShowWindow(SW_HIDE);
	}
	else {
		ShowWindow(SW_SHOW);
	}
}

void CServerProgramDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	// Decide if minimize state changed
	bool bOldMin = bMinimized_;
	if (nID == SC_MINIMIZE) {
		bMinimized_ = true;
	}
	else if (nID == SC_RESTORE) {
		bMinimized_ = false;
	}

	CDialog::OnSysCommand(nID, lParam);

	if (bOldMin != bMinimized_) {
		// Minimize state changed.  Create the systray icon and do 
		// custom taskbar button handling.
		if (bSystemTray)
		{
			SetupTrayIcon();
			SetupTaskBarButton();
		}
	}
}

void CServerProgramDlg::OnSTExit()
{
	OnCancel();
}

void CServerProgramDlg::OnSTRestore()
{
	ShowWindow(SW_RESTORE);
	bMinimized_ = false;
	SetupTrayIcon();
	SetupTaskBarButton();
}

BOOL CServerProgramDlg::DestroyWindow() 
{
 	// Get rid of systray icon
 	bMinimized_ = false;
 	SetupTrayIcon();
 	return CDialog::DestroyWindow();
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// End of System Tray Code /////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// The following block is Created by MFC and has not been modified at all.
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CServerProgramDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CServerProgramDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// End of MFC Block ////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

BOOL CServerProgramDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	//This block of code is necessary for the System Tray functionality
	if (::AfxGetApp()->m_nCmdShow & SW_MINIMIZE) {
	// User wants app to start minimized, but that only affects the 
	// main window.  So, minimize this window as well.
	PostMessage(WM_SYSCOMMAND, SC_MINIMIZE);
	}

	//This code prevents two instances of the server from being created.
	//(The second instance will exit immediately)
	::SetProp(AfxGetMainWnd()->GetSafeHwnd(),"MYSERVER",(HANDLE)1);
	CreateMutex(NULL, TRUE, "MYSERVER");
	if(GetLastError() == ERROR_ALREADY_EXISTS)
	{
		::PostQuitMessage(-1);
		return FALSE;
	}

	//The following code sets up the list control in the main dialog
	m_Users.SetExtendedStyle( m_Users.GetExtendedStyle() | LVS_EX_FULLROWSELECT );
	m_Users.InsertColumn(0,"Name",LVCFMT_LEFT,121,0);
    m_Users.InsertColumn(1,"Socket Number",LVCFMT_LEFT,100,0);
    m_Users.InsertColumn(2,"Version",LVCFMT_LEFT,65,0);
	m_Users.InsertColumn(3,"Password",LVCFMT_LEFT,117,0);
	m_Users.InsertColumn(4,"IP Address",LVCFMT_LEFT,90,0);

	//Sets the total number of users and current number of users online statistic to 0
	nUsersOnline = 0;
	nTotalUsers = 0;
	m_nUsersOnline = "0";
	m_nTotalUsers = "0";
	UpdateData(false);

	//Reads the saved server settings which are stored in the registry (so that you don't have
	//to reselect each option each time you run the server).
	ReadSettings();

	//if User Logging is enabled, this code creates the file if it doesn't already exist.
	if (bLog)
	{
		if(log.m_pStream != NULL)
			log.Close();
		WIN32_FIND_DATA fData;
		HANDLE handle = FindFirstFile(LPCTSTR(logPath),&fData); 
		if (handle == INVALID_HANDLE_VALUE)
		{
			if (log.Open (logPath, CFile::modeCreate | CFile::modeWrite) == TRUE)
				if(log.m_pStream != NULL)
					log.Close();
		}
	}

	//This runs the OnTimer User Maintenance function once per day
	SetTimer(1,86400000,NULL);		

	//If you require users to enter their password to log on, this code readies the user file (which contains their passwords) for later.
	if (bPassword)
	{
		usersFile.SetPath(userFilePath);
		usersFile.ReadFile();
	}

	//First Socket of the array to use.
	nextAvailableSocket = 0;

	//This code readies all 1000 sockets.  It informs each socket that they should send their messages to this class,
	//as well as it informs each socket of what socket number they are.
	for (int nSock=0;nSock<1000;nSock++)
	{
		Sock[nSock].hParent = m_hWnd;
		Sock[nSock].nSocket = nSock;
	}
	//Same as above, but for the socket that listens for incoming connections (when that happens, it passes the
	//connection to the next in line of the 1000 sockets.
	listenSock.hParent = m_hWnd;
	
	//Start 'er up!
	StartServer();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CServerProgramDlg::StartServer()
{
	//Create and start listening for connections
	if (listenSock.Create(nPort) && listenSock.Listen())
	{
		//If User logging is enabled, this code logs the starting up of the server.
		if (bLog)
		{
			if(log.m_pStream != NULL)
				log.Close();
			if (log.Open (logPath, CFile::modeWrite) == TRUE)
			{
				GetLocalTime(&st);
				GetTimeFormat(LOCALE_USER_DEFAULT,DATE_LONGDATE,&st,NULL,szTime,80);
				GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szDate, 80);
				char strPort[10];
				_itoa(nPort, strPort,10);
				log.SeekToEnd();
				log.WriteString("Server Started on "+CString(szDate)+" at "+CString(szTime)+" on Port "+strPort+"\n");
			}
		}
	}
}

//Called when a User Connects.  This function accepts the connection, and gets ready for the next connection.
//Once the connection is accepted, the client will attempt to log on (which has nothing to do with this function).
LRESULT CServerProgramDlg::OnUserConnect(WPARAM message,LPARAM nSocket)
{
	listenSock.Accept(Sock[nextAvailableSocket]);
	if (nextAvailableSocket==999)
		nextAvailableSocket=0;
	else
		nextAvailableSocket++;
	return (0);
}

//Called when a user sends their info to log on.
int CServerProgramDlg::UserLogOn(CString userName, CString userVersion, CString userPassword, int nSock)
{
	//If Version Checking is enabled, the user is booted off if they don't have the specified version.
	if (bVersionCheck)
	{
		if (userVersion != version)
			return -1;
	}

	//If Passwords are enabled, the user is booted off if they don't send their correct password.
	if (bPassword)
	{
		CString recordedUserPassword = usersFile.GetValue(userName,"Password");
		if (userPassword != recordedUserPassword)
			return -2;
	}
	
	//This code retrieves the users IP address.
	UINT nSize = 20;
	CString userIPAddress;
	Sock[nSock].GetPeerName(userIPAddress,nSize);
	
	//converts the users socket number to a string (so it can be inserted into the list control).
	char strSock[6];
	_itoa(nSock,strSock,10);

	//Add the user to the list control.
	m_Users.InsertItem(0,userName);
	m_Users.SetItemText(0,1,strSock);
	m_Users.SetItemText(0,2,userVersion);
	m_Users.SetItemText(0,3,userPassword);
	m_Users.SetItemText(0,4,userIPAddress);

	// If Password Checking is enabled, update the users file.
	if (bPassword)
	{
		usersFile.SetValue(userName,"Days Since Last Time Online","0");
		int timesOnline = usersFile.GetValueI(userName,"Number of Times Online");
		usersFile.SetValueI(userName,"Number of Times Online",timesOnline+1);
		usersFile.WriteFile();
	}

	//If User Logging is enabled, log this connection.
	if (bLog)
	{
		GetLocalTime(&st);
		GetTimeFormat(LOCALE_USER_DEFAULT,DATE_LONGDATE,&st,NULL,szTime,80);
		GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szDate, 80);
		log.SeekToEnd();
		log.WriteString(userName+" Connected On "+CString(szDate)+" at "+szTime+" from computer "+userIPAddress+"\n");
	}

	//Increases the total number of users and current number of users online statistic by one
	nUsersOnline++;
	nTotalUsers++;
	char strUsersOnline[8];
	char strTotalUsers[8];

⌨️ 快捷键说明

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