gh0st3.6执行流程

来源:互联网 发布:淘宝刷单增权重 编辑:程序博客网 时间:2024/06/05 23:07

1、CGh0stApp–>Initlnstance() 
1)配置界面信息及其他 
2)从.ini文件中读取监听端口ListenPort和最大连接数MaxConnection,并做相应的调整 
3)调用((CMainFrame*) m_pMainWnd)->Activate(nPort, nMaxConnection)去激活服务器,(跳到2)

2、CMainFrame–>Activate(UINT nPort, UINT nMaxConnections) 
0)1来 
1)检查是否存在m_iocpServer,如果有的话,shutdown一下 
(程序刚启动,一般是没有,这里停一下,不跟进,跟进到13) 
2)m_iocpServer新建对象,调用CIOCPServer的构造函数(跟进,到3) 
3)开启服务器,调用函数 
m_iocpServer->Initialize(NotifyProc, this, 100000, nPort)(跟进到4) 
4)获得主机名,通过主机名获得ip,并设置状态栏显示数据 
5)返回到1

3、CIOCPServer–>CIOCPServer() 
0)2来 
1)初始化套接字版本wsaData 
2)初始化一个临界区变量m_cs 
3)初始化15个iocpserver的变量, 
4)定义包标志bPacketFlag 
5)返回到2

4、CIOCPServer–>Initialize(NotifyProc, this, 100000, nPort) 
0)2来 
1)存下三个参数 
2)创建套接口m_socListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
3)创建网络事件m_hEvent = WSACreateEvent() 
4)将FD_ACCEPT事件关联到套接口上 
nRet = WSAEventSelect(m_socListen,m_hEvent,FD_ACCEPT); 
5)配置SOCKADDR_IN地址 
6)绑定套接头nRet = bind(m_socListen,(LPSOCKADDR)&saServer,sizeof(struct sockaddr)); 
7)监听端口nRet = listen(m_socListen, SOMAXCONN); 
8)开启监听线程 
m_hThread =(HANDLE)_beginthreadex(NULL,0,ListenThreadProc,(void*) this,0,&dwThreadId); 
9)跟进看一下这个监听线程都干了啥(跟进到5) 
A)初始化完成端口InitializeIOCP();(MD,数字太多,把我弄混了,居然把这个给漏了)(跳到20) 
B)返回2

5、CIOCPServer.–>ListenThreadProc(LPVOID lParam) 
0)4来 
1)无限while循环 
2)等待m_hKillEvent受信就跳出循环 
WaitForSingleObject(pThis->m_hKillEvent, 100) == WAIT_OBJECT_0 
3)插一句,受信是在CIOCPServer::stop中SetEvent(m_hKillEvent), 
就是在stop掉server的时候受信 
4)等待事件的发生,没有发生就阻塞在这里 
dwRet = WSAWaitForMultipleEvents(1,&pThis->m_hEvent,FALSE,100,FALSE); 
5)如果超时,继续while循环 
6)查看事件是什么事件 
int nRet = WSAEnumNetworkEvents(pThis->m_socListen,pThis->m_hEvent,&events); 
7)如果error的话就跳出while循环 
8)如果事件是FD_ACCEPT的话,表示有连接到来调用CIOCPSserver::OnAccept()(跟进到6) 
9)继续自循环。到5

6、CIOCPSserver–>OnAccept() 
0)5来 
1)检查m_bTimeToKill和m_bDisconnectAll,如果关闭标识为真,则直接返回 
2)接受套接字,保存套接字的地址和地址长度 
clientSocket = accept(m_socListen,(LPSOCKADDR)&SockAddr,&nLen); 
3)分配一个Context来存储套接字信息,返回值是个ClientContext指针 
ClientContext* pContext = AllocateContext(); 
(跟进转到7) 
4)检查是否分配成功,否返回, 
5)然后将客户端的套接字给pContext,pContext->m_Socket = clientSocket; 
6)修复m_wsaInBuffer结构体的长度和指针 
7)调用这个函数来创建完成端口CIOCPServer::AssociateSocketWithCompletionPort(跳到9) 
8)如果不成功的话,就删掉Context,并且关掉clientSocket和m_socListen,并返回 
9)setsockopt来启动保活机制 
setsockopt(pContext->m_Socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&chOpt, sizeof(chOpt)) 
A)设置超时信息 
B)加锁CLock cs(m_cs, “OnAccept” )并将pContext加到m_listContexts的尾部 
C)投递到I/O完成队列中, 
D)如果没有成功。则调用CIOCPSserver::RemoveStaleClient(pContext,TRUE);(挑转到10) 
TRUE 表示不需要暴力断开连接 
E)m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_CLIENT_CONNECT);通知窗口处理上线信息(先不跳,跳到16) 
F)PostRecv(pContext);(跳到12) 
G)(返回到5)

7、CIOCPServer::AllocateContext() 
0)6来 
1)用cs进行加锁操作 
2)如果m_listFreePool为不空的话,就拿出第一个来,否则新建一个ClientContext(这里跳到8) 
3)将pContext清0 
4)如果存在pContext对象的话,就再次清零(这里是不是有些重复), 
然后写明不是MainSocket,m_Dialog也清为0 
5)(返回6继续)

8、struct ClientContext 认识下这个结构体,很重要 
0)7来 
1)SOCKET m_Socket; //套接字 
2)CBuffer m_WriteBuffer; //要发送的数据 
3)CBuffer m_CompressionBuffer; // 接收到的压缩的数据 
4)CBuffer m_DeCompressionBuffer; // 解压后的数据 
5)CBuffer m_ResendWriteBuffer; // 上次发送的数据包,接收失败时重发时用 
6)int m_Dialog[2]; //放对话框列表用,第一个int是类型, 
第二个是CDialog的地址 
//这个参数非常重要,区分主套接字与各个功能间的套接字, 
//如果这个值为非NULL 则认为是功能的套接字,交给冲口处理 
//如果为NULL 则认为是主套接字,交给主套接字的上线函数处理 
//到void CMainFrame::ProcessReceiveComplete(ClientContext *pContext)分析 
7)int m_nTransferProgress; 
// Input Elements for Winsock 
8)WSABUF m_wsaInBuffer; //结构体,buffer长度和指针, 
指针指向m_byInBuffer,长度为m_byInBuffer的长度 
9)BYTE m_byInBuffer[8192]; 
// Output elements for Winsock 
A)WSABUF m_wsaOutBuffer; 
B)HANDLE m_hWriteComplete; //socket写满了,准备好要发送 
// Message counts… purely for example purposes 
C)LONG m_nMsgIn; 
D)LONG m_nMsgOut; //要发送的数据+1 
E)BOOL m_bIsMainSocket; // 是不是主socket 
F)ClientContext* m_pWriteContext; 
G)ClientContext* m_pReadContext; 
H)(返回7继续)

9、BOOL CIOCPServer::AssociateSocketWithCompletionPort(SOCKET socket, 
HANDLE hCompletionPort, DWORD dwCompletionKey) 
0)6来 
1)把socket添加到一个已有I/O完成端口的设备列表中,socket与完成端口关联 
2)(返回到6继续)

10、CIOCPServer–>RemoveStaleClient(ClientContext* pContext, BOOL bGraceful) 
0)6来 
1)CLock cs(m_cs, “RemoveStaleClient”);加锁 
2)lingerStruct和setsockopt来暴力使socket的TCP夭折(FALSE才执行) 
3)找到m_listContexts中的pContext 
4)取消掉pContext的套接口的Io CancelIo((HANDLE) pContext->m_Socket); 
5)关闭套接口, 
6)查看I/O是否完成HasOverlappedIoCompleted((LPOVERLAPPED)pContext)宏查看 
7)给界面发送断开连接的消息m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_CLIENT_DISCONNECT);(先不跳) 
8)把pContext放到m_listFreePool中(跳到11)(返回6)

11、CIOCPServer–>MoveToFreePool(pContext); 
0)10来 
1)CLock cs(m_cs, “MoveToFreePool”);加锁 
2)从m_listContexts中找到pContext后,清掉它的各种数据后,移到m_listFreePool的链尾上 
3)m_listContexts链表中移除pContext(返回10继续)

12、CIOCPServer–>PostRecv(ClientContext* pContext) 
0)6来 
1)pOverlap(IORead) 
2)WSARecv读数据到m_wsaInBuffer里 
3)如果读取失败的话,调用RemoveStaleClient(pContext, FALSE);(跳到10,然后跳回6)

13、CIOCPServer->Shutdown(); 
0)2来 
1)检查服务器是否在运行,如果否的话,直接返回m_bInit 
2)修改两个标志,m_bInit为false,m_bTimeToKill为true 
3)调用CIOCPServer::stop()(跳到14) 
4)关掉m_socListen套接口和m_hEvent事件, 
5)关掉完成端口,CIOCPServer::CloseCompletionPort()(跳转到15) 
6)删掉临界区,循环删掉m_listFreePool 
7)结束了

14、CIOCPServer->stop(); 
0)13来 
1)SetEvent(m_hKillEvent),监听线程停止循环,并结束 
2)无限等待监听线程结束WaitForSingleObject(m_hThread, INFINITE); 
3)关掉监听线程的句柄,关掉m_hKillEvent的句柄 
4)(返回13)

15、CIOCPServer–>CloseCompletionPort() 
0)13来 
1)当m_nWorkerCnt工作线程还存在,就发送 
PostQueuedCompletionStatus(m_hCompletionPort, 0, (DWORD) NULL, NULL);关掉工作线程 
2)关掉标识m_hCompletionPort 
3)遍历m_listContexts链表,删掉每一个Client,跳到10 
4)最后删掉所有 
5)返回到13

16、CALLBACK CMainFrame::NotifyProc(LPVOID lpParam, ClientContext *pContext, UINT nCode) 
0)6来,10来 
1)g_pConnectView获得主窗体(全局) 
2)把CMainFram的m_iocpServer给gh0stView的m_iocpServer 
3)设置状态条的流量值 
4)如果nCode是NC_CLIENT_DISCONNECT的话,向窗口发送WM_REMOVEFROMLIST消息 
5)如果是NC_RECEIVE则调用ProcessReceive,ProcessReceive(pContext); 跳到17 
6)如果是NC_RECEIVE_COMPLETE则调用ProcessReceiveComplete函数,跳到18

17、CMainFrame::ProcessReceive(ClientContext *pContext) 
0)16来 
1)CDialog dlg = (CDialog )pContext->m_Dialog[1],获得窗口指针 
2)pContext->m_Dialog[0]调用相应窗体(摄像头、屏幕监控、语音)的OnReceive函数,处理数据 
3)返回16

18、CMainFrame::ProcessReceiveComplete(ClientContext *pContext) 
0)16来 
1)获得相应的窗体CDialog dlg = (CDialog )pContext->m_Dialog[1]; 
2)pContext->m_Dialog[0]),((CFileManagerDlg *)dlg)->OnReceiveComplete(); 
根据不同的消息交给不同的窗体处理,所有的完成的信息 
3)pContext->m_DeCompressionBuffer.GetBuffer(0)[0], 
根据加密数据的第一位来判断包的类型 
4)Send函数,m_iocpServer->Send(pContext, (LPBYTE)&bToken, sizeof(bToken)); 
5)

19、CIOCPServer–>Send(ClientContext* pContext, LPBYTE lpData, UINT nSize) 
0)18来 
1)compress来压缩要传送的数据 
2)向m_WriteBuffer中写入包标志m_bPacketFlag、整个包的大小,数据包的大小,写入压缩后的数据 
3)把要发送的数据(加密后的)写到lpResendWriteBuffer 
4)将lpResendWriteBuffer写入m_ResendWriteBuffer 
5)如果要发送的数据的大小不大于0的话,就发备份的数据 
6)等待m_hWriteComplete准备好(等CIOCPServer::OnClientWriting) 
7)异读写结构体,置为IO写 
8)post到完成端口队列,并将pContext->m_nMsgOut++ 
9)回到18

20、CIOCPServer–>InitializeIOCP(void) 
0)4来 
1)创建一个原始套接口s= socket(AF_INET, SOCK_STREAM, IPPROTO_IP) 
2)m_hCompletionPort = CreateIoCompletionPort( (HANDLE)s, NULL, 0, 0 );//创建io完成端口 
3)获得系统信息GetSystemInfo( &systemInfo ); 
4)m_nThreadPoolMin=m_nThreadPoolMax=线程数*2 
5)m_nCPULoThreshold和m_nCPUHiThreshold CPU的使用量 
6)初始化查询CPU的使用量 CPU.init()(跳到21) 
7)计算工作线程数nWorkerCnt = systemInfo.dwNumberOfProcessors * HUERISTIC_VALUE; 
8)循环创建工作线程 
hWorker = (HANDLE)_beginthreadex(NULL,0,ThreadPoolFunc,(void*) this,0,&nThreadID); 
9)工作线程的回调函数ThreadPoolFunc(跳到22)

21、CCpuUsage–>Init() 
0)20来 
1)定义一个查询结构PdhOpenQuery(NULL, 1, &m_hQuery) 
2)pdh_status = PdhAddCounter(m_hQuery, szCounterName, (DWORD) m_pCounterStruct, 
&(m_pCounterStruct->hCounter)) 
将查询结构添加到查询句柄中 
3)返回20

22、CIOCPServer–>ThreadPoolFunc (LPVOID thisContext) 
0)20来 
1)m_CurrentThreads自自加锁,m_nBusyThreads自加锁 
2)大for循环 
3)m_nBusyThreads解锁 
4)取得一个完成端口请求 
BOOL bIORet = GetQueuedCompletionStatus(hCompletionPort,&dwIoSize, 
(LPDWORD) &lpClientContext,&lpOverlapped, INFINITE); 
5)CONTAINING_RECORD(address, type, field) ((type *)( \ 
(PCHAR)(address) - \ 
(ULONG_PTR)(&((type *)0)->field))) 
宏:指向整个的定义结构,这样就能指向带有附加数据的整个OVERLAPPEDPLUS类型, 
并且根据附加的数据的m_ioType域的不同,进行不同的处理 
6)m_nBusyThread自锁 
7)get不成功的话以及超时就移除所有ClientContext 
8)继续循环 
9)没有error的话,当前线程是唤醒的工作线程,并且唤醒的线程数少于最大线程池数,并且cpu的使用量大于最大线程利用率的 
再开一个线程,目测这个被注释掉了,并不需要申请额外的线程到线程池了, 
A)get不成功,线程超时,没有取得Contenxt,CPU使用少于最少,当前线程数大于最小线程池数的画,退出循环 
B)如果get成功,调用ProcessIOMessage(pOverlapPlus->m_ioType, lpClientContext, dwIoSize);(跳到23) 
C)解锁m_nWorkerCnt、m_nCurrentThreads、m_nBusyThreads 
D)线程结束

23、CIOMessageMap的虚函数 
IO_MESSAGE_HANDLER(IORead, OnClientReading)(跳到24) 
IO_MESSAGE_HANDLER(IOWrite, OnClientWriting)() 
IO_MESSAGE_HANDLER(IOInitialize, OnClientInitializing) 
0)22来 
1)根据消息的类型,选择不同的函数

24、CIOCPServer::OnClientReading(ClientContext* pContext, DWORD dwIoSize) 
0)23来 
1)CLock cs(CIOCPServer::m_cs, “OnClientReading”);加锁 
2)计算接受速度,(这里值得好好思考下) 
3)没有数据,说明遇到不可预知的错误,直接删掉连接 
4)如果包里只有Gh0st数据的话,主控端就重新发送数据 
5)把m_byInBuffer中的数据写入m_CompressionBuffer 
6)通知界面,收到数据了 goto 16 
7)while m_CompressionBuffer中的数据大于13的时候 
8)拷出包头,并对比下是不是Gh0st,

0 0
原创粉丝点击