代码:
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
{
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);
}
有些东西我省略了方便大牛查看 帮忙解释下 啥云因