创建一个基于MFC的控制台应用程序,添加内容如下:
stdafx.h中添加:
// TODO: 在此处引用程序需要的其他头文件
#include <stdio.h>
#include <tchar.h>
#include <process.h>
#include <tchar.h>
#include <iostream>
#include <algorithm>
#include <winsock2.h>
#include <crtdbg.h>
#include <cstring>
#include <iomanip>
#include <list>
//cpp实现文件内容:
// IocpTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "IocpTest.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#pragma comment(lib, "ws2_32.lib")
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
#define LOC_PORT 5678
#define LOC_ADDR "127.0.0.1"
class CSocketObject
{
public:
CSocketObject(){WSAStartup(MAKEWORD(2,2), &m_wsaData);}
virtual ~CSocketObject(){WSACleanup();}
public:
virtual void Run() = 0;
protected:
WSADATA m_wsaData;
};
class CTcpServer : public CSocketObject
{
public:
virtual void Run();
private:
HANDLE m_hCompPort;
typedef struct
{
OVERLAPPED ovlp;
SOCKET sock;
sockaddr_in tAddr;
WSABUF buf;
char ucOpera;
}EVENT_T;
enum{OP_RECV, OP_SEND};
static unsigned int __stdcall WorkerThreadProc(void *pvArg);
static int dwWorkerID;
};
int CTcpServer::dwWorkerID = 1;
unsigned int CTcpServer::WorkerThreadProc(void *pvArg)
{
DWORD dwTrans;
EVENT_T *ptEv;
OVERLAPPED *povlp;
CTcpServer *poTcpServer = (CTcpServer*)pvArg;
int dwID = CTcpServer::dwWorkerID++;
while (1)
{
GetQueuedCompletionStatus(poTcpServer->m_hCompPort, &dwTrans, (DWORD*)&ptEv, &povlp, INFINITE);
printf("worker %d get the completion status/n", dwID);
switch (ptEv->ucOpera)
{
case CTcpServer::OP_RECV:
if (0 == dwTrans)
{
printf("client: %s leave/n", inet_ntoa(ptEv->tAddr.sin_addr));
closesocket(ptEv->sock);
delete[] ptEv->buf.buf;
delete ptEv;
}
else
{
ptEv->buf.buf[dwTrans] = 0;
printf("message from %s: %s/n", inet_ntoa(ptEv->tAddr.sin_addr), ptEv->buf.buf);
ZeroMemory(&ptEv->ovlp, sizeof(ptEv->ovlp));
DWORD dwRecvd, dwFlags = 0;
WSARecv(ptEv->sock, &ptEv->buf, 1, &dwRecvd, &dwFlags, &ptEv->ovlp, NULL);
}
break;
case CTcpServer::OP_SEND:
break;
default:
break;
}
}
return 0;
}
void CTcpServer::Run()
{
SOCKET tSock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
SOCKADDR_IN tAddr, tClientAddr;
tAddr.sin_family = AF_INET;
tAddr.sin_port = htons(LOC_PORT);
tAddr.sin_addr.s_addr = inet_addr(LOC_ADDR);
_ASSERT(bind(tSock,(SOCKADDR*)&tAddr, sizeof(tAddr)) == 0);
m_hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 5);
CloseHandle((HANDLE)_beginthreadex(NULL, 0, WorkerThreadProc, this, 0, NULL));
Sleep(50);
CloseHandle((HANDLE)_beginthreadex(NULL, 0, WorkerThreadProc, this, 0, NULL));
listen(tSock, 5);
for (;;)
{
int dwNameLen = sizeof(tClientAddr);
SOCKET acceptSocket = accept(tSock, (sockaddr*)&tClientAddr, &dwNameLen);
if (acceptSocket == INVALID_SOCKET)
{
continue;
}
else
{
printf("client: %s come in/n", inet_ntoa(tClientAddr.sin_addr));
}
EVENT_T *ptEv = new EVENT_T;
ptEv->sock = acceptSocket;
memcpy(&ptEv->tAddr, &tClientAddr, sizeof(tClientAddr));
CreateIoCompletionPort((HANDLE)acceptSocket, m_hCompPort, (DWORD)ptEv, 5);
DWORD dwRecvd, dwFlags = 0;
ZeroMemory(&ptEv->ovlp, sizeof(ptEv->ovlp));
ptEv->buf.buf = new char[1024];
ptEv->buf.len = 1024;
ptEv->ucOpera = CTcpServer::OP_RECV;
WSARecv(acceptSocket, &ptEv->buf, 1, &dwRecvd, &dwFlags, &ptEv->ovlp, NULL);
}
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败/n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
CSocketObject *poSockServer = new CTcpServer;
poSockServer->Run();
delete poSockServer;
AfxMessageBox(_T("Hello"));
return 0;
}
return nRetCode;
}
测试:在ie浏览器中输入:http://120.0.0.1:5678看到结果
2478

被折叠的 条评论
为什么被折叠?



