第十一课、加入Socket数据传输的内核
2.4 加入端口监听功能
1.分析gh0st监听端口的函数:
Activate(UINT nPort, UINT nMaxConnections)
2.需要一个回调函数,用于分类处理一些功能消息
NotifyProc
3.复制NotifyProc 代码 到我们的dlg类中, 去掉多余的代码
头文件声明:
protected:
static void CALLBACK NotifyProc(LPVOID lpParam, ClientContext *pContext, UINT nCode);//消息处理函数
源文件实现:
void CALLBACK CVeryEvilDlg::NotifyProc(LPVOID lpParam, ClientContext *pContext, UINT nCode)
{
try
{
switch (nCode)
{
case NC_CLIENT_CONNECT:
break;
case NC_CLIENT_DISCONNECT:
//g_pConnectView->PostMessage(WM_REMOVEFROMLIST, 0, (LPARAM)pContext);
break;
case NC_TRANSMIT:
break;
case NC_RECEIVE:
//ProcessReceive(pContext); //这里是有数据到来 但没有完全接收
break;
case NC_RECEIVE_COMPLETE:
//ProcessReceiveComplete(pContext); //这里时完全接收 处理发送来的数据 跟进 ProcessReceiveComplete
break;
}
}catch(...){}
}
4,在dlg头文件还应该包含: #include "include\IOCPServer.h"
5.同样复制Activate 函数到我们的工程中去
声明:
protected:
void Activate(UINT nPort, UINT nMaxConnections); //激活监听端口函数
函数实现:
void CVeryEvilDlg::Activate(UINT nPort, UINT nMaxConnections)
{
CString str;
if (m_iocpServer != NULL)
{
m_iocpServer->Shutdown();
delete m_iocpServer;
}
m_iocpServer = new CIOCPServer;
////lang2.1_8
// 开启IPCP服务器 最大连接 端口 查看NotifyProc回调函数 函数定义
if (m_iocpServer->Initialize(NotifyProc, this, 100000, nPort))
{
char hostname[256];
gethostname(hostname, sizeof(hostname));
HOSTENT *host = gethostbyname(hostname);
if (host != NULL)
{
for ( int i=0; ; i++ )
{
str += inet_ntoa(*(IN_ADDR*)host->h_addr_list[i]);
if ( host->h_addr_list[i] + host->h_length >= host->h_name )
break;
str += "/";
}
}
m_wndStatusBar.SetPaneText(0, str);
str.Format("端口: %d", nPort);
m_wndStatusBar.SetPaneText(2, str);
}
else
{
str.Format("端口%d绑定失败", nPort);
m_wndStatusBar.SetPaneText(0, str);
m_wndStatusBar.SetPaneText(2, "端口: 0");
}
m_wndStatusBar.SetPaneText(3, "连接: 0");
}
函数修改部分:if (m_iocpServer->Initialize(NotifyProc, NULL, 100000, nPort))
应为这里我们用不上这个指针了,就由this改为NULL。
6,在dlg的cpp文件的首部(用户自定义数据去声明) :CIOCPServer *m_iocpServer = NULL; //CIOCPServer类对象指针,方便以后直接操作
7,在dlg的OnInitDialog中合适的位置(在我们的测试函数Test()之前调用)调用激活监听端口函数
Activate(2000,9999);//开启端口监听
7.监听后添加日志消息,把gh0st原本在状态栏显示的绑定状态信息在日志控件输出显示
部分代码如下:
void CVeryEvilDlg::Activate(UINT nPort, UINT nMaxConnections)
{
.......................................
/*
m_wndStatusBar.SetPaneText(0, str);
str.Format("端口: %d", nPort);
m_wndStatusBar.SetPaneText(2, str);
*/
str.Format("监听端口: %d成功", nPort);
ShowMessage(true,str);
}
else
{
/*
str.Format("端口%d绑定失败", nPort);
m_wndStatusBar.SetPaneText(0, str);
m_wndStatusBar.SetPaneText(2, "端口: 0");
*/
str.Format("监听端口: %d失败", nPort);
ShowMessage(false,str);
}
//m_wndStatusBar.SetPaneText(3, "连接: 0");
}
8.测试 netstat -an
第十二课、加入Socket数据传输的内核
2.5 ini 配置文件的读写
1.认识几个读写ini文件的 API
BOOL WINAPI WritePrivateProfileString( //在ini文件中写入指定字符
__in LPCTSTR lpAppName, //节的名字
__in LPCTSTR lpKeyName, //键值的名字
__in LPCTSTR lpString, //要写入的内容 如果为NULL 则删除该键
__in LPCTSTR lpFileName //ini 文件名
);
UINT WINAPI GetPrivateProfileInt( //从ini文件中读取指定字符
__in LPCTSTR lpAppName, //节名字
__in LPCTSTR lpKeyName, //键值
__in INT nDefault, //读取的内容
__in LPCTSTR lpFileName //ini文件名
);
2.gh0st工程中已经对ini文件的读写有了很好的封装,我们有了初步的认识之后,底层实现我们也有了初步了解,现在就可以使用封装好的类了。
3.复制gh0st工程下的iniFile.h和iniFile.cpp到我们的工程中并添加,注释掉inifile.cpp中的#include "gh0st.h"
4查看gh0st是怎样读写ini文件的,到CGh0stApp::InitInstance()
源码中讲解
5.大家可能会奇怪 ini 文件名从何而来,我们来看一下这个类的构造函数CIniFile::CIniFile()
源码中讲解
6.剩下还有好多封装好的功能,有兴趣大家自己研究吧
7.声明一个ini 文件处理的变量CIniFile m_IniFile; 这个变量不应该到处声明,最好只声明一次,因为构造函数中,有一个文件处理的过程,影响程序运行速度,
这样最好在CVeryEvilApp类中声明,以后使用就可以这样调用:
((CVeryEvilApp*)AfxGetApp())->m_IniFile
8.为CPCRemoteDlg 添加一个成员函数ListenPort 用于管理监听的代码,写入内容:
/****************从ini读取配置文件并设置监听端口函数*****************************/
void CVeryEvilDlg::ListenPort(void)
{
int nPort = ((CVeryEvilApp*)AfxGetApp())->m_IniFile.GetInt("Settings", "ListenPort"); //读取ini 文件中的监听端口
int nMaxConnection = ((CVeryEvilApp*)AfxGetApp())->m_IniFile.GetInt("Settings", "MaxConnection"); //读取最大连接数
if (nPort == 0)
nPort = 80;
if (nMaxConnection == 0)
nMaxConnection = 10000;
Activate(nPort,nMaxConnection); //开始监听
}
9.替换OnInitDialog()中 Activate 函数改为ListenPort。
10.处理崩溃
在IniFIle类的构造函数中
::GetModuleFileName(AfxGetInstanceHandle(), szAppName, sizeof(szAppName));
改为:
::GetModuleFileName(NULL, szAppName, sizeof(szAppName));
11.添加监听端口的设置
(1)添加对话框IDD_DIALOG_SETTING
(2)添加两个编辑框控件(监听端口,最大连接数) IDC_EDIT_PORT ,IDC_EDIT_MAX
(3)添加控件关联UINT变量 m_nListernProt;
m_nMax_Connect;
(4)为话框添加一个关联类 CSettingDlg
(5)为对话框的“确定”按钮添加按钮事件并写入代码:
void CSettingDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
((CVeryEvilApp *)AfxGetApp())->m_IniFile.SetInt("Settings", "ListenPort", m_nListernProt); //向ini文件中写入值
((CVeryEvilApp *)AfxGetApp())->m_IniFile.SetInt("Settings", "MaxConnection", m_nMax_Connect);
MessageBox("设置成功,重启本程序后生效!");
CDialogEx::OnOK();
}
(6)在我们的主界面Dlg类的cpp文件包含头文件 #include "SettingDlg.h"
(7)在以前我们的参数设置函数内添加代码
void CVeryEvilDlg::OnMainSet()
{//设置
// TODO: 在此添加命令处理程序代码
CSettingDlg SettingDlg;
SettingDlg.DoModal();
}
12.测试