class CClientContext //To store and manage client related information
{
private:
OVERLAPPED *m_pol;
WSABUF *m_pwbuf;
int m_nTotalBytes;
int m_nSentBytes;
SOCKET m_Socket; //accepted socket
int m_nOpCode; //will be used by the worker thread to decide what operation to perform
char m_szBuffer[MAX_BUFFER_LEN];
public:
void SetOpCode(int n){m_nOpCode = n;}
int GetOpCode(){return m_nOpCode;}
void SetTotalBytes(int n){m_nTotalBytes = n;}
int GetTotalBytes(){return m_nTotalBytes;}
void SetSentBytes(int n){m_nSentBytes = n;}
void IncrSentBytes(int n){m_nSentBytes += n;}
int GetSentBytes() {return m_nSentBytes;}
void SetSocket(SOCKET s){m_Socket = s;}
SOCKET GetSocket(){return m_Socket;}
void SetBuffer(char *szBuffer){strcpy(m_szBuffer, szBuffer);}
void GetBuffer(char *szBuffer){strcpy(szBuffer, m_szBuffer);}
void ZeroBuffer(){ZeroMemory(m_szBuffer, MAX_BUFFER_LEN);}
void SetWSABUFLength(int nLength){m_pwbuf->len = nLength;}
int GetWSABUFLength(){return m_pwbuf->len;}
WSABUF* GetWSABUFPtr(){return m_pwbuf;}
OVERLAPPED* GetOVERLAPPEDPtr(){return m_pol;}
void ResetWSABUF()
{ZeroBuffer();
m_pwbuf->buf = m_szBuffer;
m_pwbuf->len = MAX_BUFFER_LEN;
}
CClientContext()
{
m_pol = new OVERLAPPED;
m_pwbuf = new WSABUF;
ZeroMemory(m_pol, sizeof(OVERLAPPED));
m_Socket = SOCKET_ERROR;
ZeroMemory(m_szBuffer, MAX_BUFFER_LEN);
m_pwbuf->buf = m_szBuffer; //这句话的意思是不是说 将m_szBuffer 指针给了buf
m_pwbuf->len = MAX_BUFFER_LEN; //也就是说 实际上WSABUF里的数组指针指向的是m_szBuffer 实际接收的数据是 在m_szBuffer数组里 问题
m_nOpCode = 0;
m_nTotalBytes = 0;
m_nSentBytes = 0;
}
};
std::vector<CClientContext *> g_ClientContext;
bool InitializeIOCP();
bool Initialize();
void CleanUp();
void DeInitialize();
DWORD WINAPI AcceptThread(LPVOID lParam);
void AcceptConnection(SOCKET ListenSocket);
bool AssociateWithIOCP(CClientContext *pClientContext);
DWORD WINAPI WorkerThread(LPVOID lpParam);
void WriteToConsole(char *szFormat, ...);
void AddToClientList(CClientContext *pClientContext);
void RemoveFromClientListAndFreeMemory(CClientContext *pClientContext);
void CleanClientList();
int GetNoOfProcessors();
#endif
int main(int argc, char *argv[])
{
Initialize();
SOCKET ListenSocket;
struct sockaddr_in ServerAddress;
ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
bind(ListenSocket, (struct sockaddr *) &ServerAddress, sizeof(ServerAddress));
listen(ListenSocket,SOMAXCONN))
g_hAcceptEvent = WSACreateEvent();
WSAEventSelect(ListenSocket, g_hAcceptEvent, FD_ACCEPT);
DWORD nThreadID;
g_hAcceptThread = CreateThread(0, 0, AcceptThread, (void *)ListenSocket, 0, &nThreadID);
}
bool InitializeIOCP()
{
g_hIOCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 );
DWORD nThreadID;
for (int ii = 0; ii < g_nThreads; ii++)
{
g_phWorkerThreads[ii] = CreateThread(0, 0, WorkerThread, (void *)(ii+1), 0, &nThreadID);
}
return true;
}
DWORD WINAPI AcceptThread(LPVOID lParam)
{
SOCKET ListenSocket = (SOCKET)lParam;
WSANETWORKEVENTS WSAEvents;
while(WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
{
if (WSA_WAIT_TIMEOUT != WSAWaitForMultipleEvents(1, &g_hAcceptEvent, FALSE, 0, FALSE))
{
void AcceptConnection(SOCKET ListenSocket)
{
sockaddr_in ClientAddress;
int nClientLength = sizeof(ClientAddress);
SOCKET Socket = accept(ListenSocket, (sockaddr*)&ClientAddress, &nClientLength);
CClientContext *pClientContext = new CClientContext;
pClientContext->SetOpCode(OP_READ); //
pClientContext->SetSocket(Socket);
AddToClientList(pClientContext); //这里是添加到列表里的
if (true == AssociateWithIOCP(pClientContext)) //请问这个关联操作会触发OP_READ 完成操作事件吗 问题1 ?????????
{
pClientContext->SetOpCode(OP_WRITE);
WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr(); //我想这里的指针 得到指针 应该可以改变pClientContext 里的OVERLAPPED结构指针里的数据吧
DWORD dwFlags = 0; DWORD dwBytes = 0;
//这里是接收一个字节 搞不懂为啥是一个字节 为啥 要接收难道我发送不行吗 问题2 ?????????
int nBytesRecv = WSARecv(pClientContext->GetSocket(), p_wbuf, 1,&dwBytes, &dwFlags, p_ol, NULL);
}
}
bool AssociateWithIOCP(CClientContext *pClientContext)
{
HANDLE hTemp = CreateIoCompletionPort((HANDLE)pClientContext->GetSocket(), g_hIOCompletionPort, (DWORD)pClientContext, 0);
return true;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int nThreadNo = (int)lpParam;
void *lpContext = NULL;
OVERLAPPED *pOverlapped = NULL;
CClientContext *pClientContext = NULL;
DWORD dwBytesTransfered = 0;
int nBytesRecv = 0;
int nBytesSent = 0;
DWORD dwBytes = 0, dwFlags = 0;
while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
{
BOOL bReturn = GetQueuedCompletionStatus(g_hIOCompletionPort,&dwBytesTransfered,(LPDWORD)&lpContext,&pOverlapped,INFINITE);
pClientContext = (CClientContext *)lpContext;
WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();
switch (pClientContext->GetOpCode())
{
case OP_READ:
pClientContext->IncrSentBytes(dwBytesTransfered); //插入到m_nSentBytes 已经传输的字节数
if(pClientContext->GetSentBytes() < pClientContext->GetTotalBytes()) //判断发送的数据是否小于总共要发送的数据 m_nTotalBytes
{
pClientContext->SetOpCode(OP_READ); //如果是 则设置标志为OP_READ 这里设置为 OP_READ 我想应该谁重复发送吧
p_wbuf->buf += pClientContext->GetSentBytes(); //向后移动 然后
p_wbuf->len = pClientContext->GetTotalBytes() - pClientContext->GetSentBytes();
dwFlags = 0;
nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1, &dwBytes, dwFlags, p_ol, NULL);
}
else //到这里的意思是发送完毕吗 按道理这里应该也要设置为OP_READ 来实现重复接收啊 为啥是OP_WRITE
{
pClientContext->SetOpCode(OP_WRITE); //如果发送的数据 大于总共要发送的 到这一步 设置开始接收数据 触发下一个事件
//为什么 没有没有关于WSARecv的 而且有也只有一个字节 难道接收只接收一个字节吗 问题 3?????????
pClientContext->ResetWSABUF(); //清空WSABUF结构
dwFlags = 0;
nBytesRecv = WSARecv(pClientContext->GetSocket(), p_wbuf, 1,&dwBytes, &dwFlags, p_ol, NULL);
}
break;
case OP_WRITE:
char szBuffer[MAX_BUFFER_LEN];
pClientContext->GetBuffer(szBuffer); //接收到的字节 怎么接收的没说啊 为啥只接收了一个字节 接受一个缓冲区为啥就能打印不继续接收 难道 继续接收应该设置下面那个标志为 OP_WRITE //问题4??????
WriteToConsole("\nThread %d: The following message was received: %s", nThreadNo, szBuffer);
pClientContext->SetOpCode(OP_READ); //继续接收 应该设置这个标志为OP_WRITE 为啥
//设置发送的字节数为 0 总发送字节数为 接收到的字节数
pClientContext->SetTotalBytes(dwBytesTransfered);
pClientContext->SetSentBytes(0);
p_wbuf->len = dwBytesTransfered;
dwFlags = 0;
nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,&dwBytes, dwFlags, p_ol, NULL);
}
有些东西我省略了方便大牛查看 帮忙解释下 啥云因
[课程]Linux pwn 探索篇!