📄 serverdlg.cpp
字号:
// ServerDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Server.h"
#include "ServerDlg.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()
/////////////////////////////////////////////////////////////////////////////
// CServerDlg dialog
CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
: CDialog(CServerDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CServerDlg)
m_selected = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_plistening=NULL;
}
void CServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CServerDlg)
DDX_Control(pDX, IDC_CLOSE, m_close);
DDX_Control(pDX, IDC_START, m_start);
DDX_Control(pDX, IDC_ONLINE, m_namelist);
DDX_Control(pDX, IDC_CHATMSG, m_chatmsg);
DDX_CBString(pDX, IDC_ONLINE, m_selected);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServerDlg, CDialog)
//{{AFX_MSG_MAP(CServerDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_START, OnStart)
ON_BN_CLICKED(IDC_CLOSE, OnClose)
ON_BN_CLICKED(IDC_QUIT, OnQuit)
ON_CBN_SELCHANGE(IDC_ONLINE, OnSelchangeOnline)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerDlg message handlers
BOOL CServerDlg::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
// TODO: Add extra initialization here
m_close.EnableWindow(FALSE); //没启动服务器前不允许关闭服务器
return TRUE; // return TRUE unless you set the focus to a control
}
void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 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 CServerDlg::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 CServerDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//处理客户端的连接信息
void CServerDlg::accept()
{
//生成一个新的套节字与客户端通讯
CChatSocket* psocket=new CChatSocket(this);
if(m_plistening->Accept(*psocket))
{
psocket->Init(); //初始化文件对象
psocket->seq=m_tempseq++; //给客户端赋一个序号
m_onlinelist.AddTail(psocket);//将该套节字保存到m_onlinelist链表中
}
else
delete psocket;
}
//接收数据
void CServerDlg::readall(CChatSocket* psocket)
{
CMsg msg;
do{
readmsg(psocket,msg);
if(m_plistening==NULL)
return;
}while(!psocket->m_pin->IsBufferEmpty());//缓冲区包含多个数据消息,需要循环直到所有的数据都被读出,并且缓冲区被清空
}
void CServerDlg::OnDestroy()//关闭对话框
{
CDialog::OnDestroy();
if(m_plistening) //如果现在还有监听套节字,释放。
delete m_plistening;
CChatSocket* psocket;
CMsg msg;
msg.msgtype=MSG_STC_serverdown;//消息格式:S->C 服务器端关闭
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;)//通知所有客户端,服务器已关闭
{
psocket=(CChatSocket*)m_onlinelist.GetNext(pos);
sendmsg(psocket,msg);
}
// TODO: Add your message handler code here
}
//接收数据
void CServerDlg::readmsg(CChatSocket* psocket,CMsg& msg)
{
TRY
{
psocket->receivemsg(msg);
msginterpreter(msg); //对消息进行处理
}
CATCH(CFileException, e)
{
CString strTemp;
if (strTemp.LoadString(IDS_SENDERROR))
MessageBox(strTemp);
}
END_CATCH
}
void CServerDlg::msginterpreter(CMsg &msg)//对消息进行处理
{
switch(msg.msgtype)
{
case MSG_CTC:
SendToClient(msg);
break;
case MSG_CTS_newclient: //客户端上线
InitNewClient(msg); //新上线的客户端接收在线的客户信息和序号
UpdateOnlineClient(msg);//更新所有客户端
break;
case MSG_CTS_clientdown: //客户端下线
UpdateOnlineClient(msg);//更新所有客户端
break;
default:
MessageBox("Undealed socket error!");
break;
}
}
void CServerDlg::OnStart() //启动服务器
{
// TODO: Add your control notification handler code here
m_plistening=new CListeningSocket(this);//创建监听套节字
if(m_plistening->Create(5555))//调用Bind()函数将此Socket绑定到指定的地址上
m_plistening->Listen();
m_tempseq=0;
m_start.EnableWindow(FALSE);//禁止再启动服务器
m_close.EnableWindow(TRUE); //允许关闭服务器
}
void CServerDlg::OnClose()//关闭服务器
{
// TODO: Add your control notification handler code here
m_close.EnableWindow(FALSE);//不允许再关闭服务器
delete m_plistening; //释放监听套节字
CChatSocket* psocket;
CMsg msg;
msg.msgtype=MSG_STC_serverdown;//消息格式:S->C 服务器端关闭
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;)//通知所有客户端,服务器已关闭
{
psocket=(CChatSocket*)m_onlinelist.GetNext(pos);
sendmsg(psocket,msg);
}
m_plistening=NULL;//防止关闭对话框时再释放监听套节字
m_start.EnableWindow(TRUE);//允许再启动服务器
int n=m_namelist.GetCount();//获得客户端数目
while(n--)
m_namelist.DeleteString(0);//清除所有客户端记录
m_onlinelist.RemoveAll(); //释放所有的套节字
}
void CServerDlg::SendToClient(CMsg &msg)//将信息发送给客户端
{
CChatSocket* psrc=NULL,*pdest=NULL,*psocket;
if(msg.from==msg.to)
{
return;
}
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;)
{
psocket=(CChatSocket*)m_onlinelist.GetNext(pos);
if(!pdest&&psocket->seq==msg.to)//查找数据目的端套节字
pdest=psocket;
else if(!psrc&&psocket->seq==msg.from)//查找数据源端套节字
psrc=psocket;
else if(pdest&&psrc)
break;
}
if(!pdest&&!psrc)
{
MessageBox("Message send error!");
return;
}
sendmsg(pdest,msg);
CString show=psrc->m_chatname+" 对 "+pdest->m_chatname+" 说:";
m_chatmsg.AddString(show);
m_chatmsg.AddString(" "+msg.chatcontent);
}
void CServerDlg::InitNewClient(const CMsg &msg)//新上线的客户端接收在线的客户信息和序号
{
CChatSocket* psocket;
bool found=false;
CMsg smsg;
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;)
{
psocket=(CChatSocket*)m_onlinelist.GetNext(pos);
if(psocket->seq==msg.from)
{
psocket->m_chatname=msg.chatcontent;//新上线客户端用户名
m_namelist.AddString(msg.chatcontent);
smsg.msgtype=MSG_STC_yourmsg;
smsg.from=psocket->seq;//smsg代表要发送的信息;smsg.from,psocket->seq代表新上线客户端自己的序号
sendmsg(psocket,smsg);
found=true;
}
}
if(found)
{
CChatSocket* p;
smsg.msgtype=MSG_STC_alonline;//把在线的客户端信息发给新上线的客户端
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;)
{
p=(CChatSocket*)m_onlinelist.GetNext(pos);
if(p->seq!=msg.from)
{
smsg.chatcontent=p->m_chatname;
smsg.from=p->seq;
sendmsg(psocket,smsg);
}
}
}
}
void CServerDlg::UpdateOnlineClient(const CMsg& msg)//更新在线客户端名单
{
CChatSocket* psocket;
CMsg smsg;
if(msg.msgtype==MSG_CTS_newclient)//判断消息格式
smsg.msgtype=MSG_STC_newclient;
else
smsg.msgtype=MSG_STC_clientdown;
smsg.from=msg.from;
int i=0;
POSITION prepos;
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;i++)
{
prepos=pos;
psocket=(CChatSocket*)m_onlinelist.GetNext(pos);
if(psocket->seq==msg.from&&msg.msgtype==MSG_CTS_clientdown)//客户端下线
{
m_onlinelist.RemoveAt(prepos);//清除该客户端套接字
m_namelist.DeleteString(i);//清除客户端序号
}
else if(psocket->seq!=msg.from)//更新所有客户端在线用户信息
{
smsg.to=psocket->seq;
smsg.chatcontent=msg.chatcontent;
sendmsg(psocket,smsg);
}
}
}
void CServerDlg::sendmsg(CChatSocket *psocket, CMsg &msg)//消息发送
{
TRY
{
psocket->sendmsg(msg);
}
CATCH(CFileException, e)
{
CString strTemp;
if (strTemp.LoadString(IDS_SENDERROR))
MessageBox(strTemp);
}
END_CATCH
}
void CServerDlg::OnQuit() //退出
{
// TODO: Add your control notification handler code here
OnOK();
}
void CServerDlg::OnSelchangeOnline()
{
// TODO: Add your control notification handler code here
int nIndex;
nIndex=m_namelist.GetCurSel();
m_namelist.GetLBText(nIndex,m_selected);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -