iocp一段服务器代码

创建一个基于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看到结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值