亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? iocp.h

?? 基于完成端口的TCP網絡通信框架實現 工程iocp中包含了框架實現的所有代碼
?? H
字號:
#pragma once
#include <winsock2.h>
#include <windows.h>
#include <assert.h>
#include <list>
#include <vector>
#include <map>
#include "iocpapi.h"
using std::list;
using std::vector;
using std::map;
using std::make_pair;

#define for_each_iter(container,iter) \
  for(iter=container.begin();iter!=container.end();++iter)

#define for_each_iter_safe(container,iter,iterNext) \
  for(iter=container.begin(),iterNext=iter,++iterNext; \
      iter!=container.end(); \
      iter=iterNext,++iterNext)
class SysMutex
{
public:
  virtual ~SysMutex(){}
  virtual void Lock() = 0;
  virtual void Unlock() = 0;
};

class Locker
{
public:
  explicit Locker(SysMutex *mutex){m_mutex = mutex;m_mutex->Lock();}
  ~Locker(){m_mutex->Unlock();}
private:
  SysMutex *m_mutex;
};

class UserMutex: public SysMutex
{
public:
  UserMutex(){InitializeCriticalSection(&m_cs);}
  ~UserMutex(){DeleteCriticalSection(&m_cs);}
  void Lock(){EnterCriticalSection(&m_cs);}
  void Unlock(){LeaveCriticalSection(&m_cs);}
private:
  CRITICAL_SECTION m_cs;
};

class SysEvent
{
public:
  SysEvent(bool bManualReset = false){m_hEvent=CreateEvent(NULL, bManualReset, false, NULL);}
  ~SysEvent(){CloseHandle(m_hEvent);}
  void Set(){SetEvent(m_hEvent);}
  bool Wait(unsigned int ms = INFINITE){return WAIT_OBJECT_0 == WaitForSingleObject(m_hEvent, ms);}
  void Reset(){ResetEvent(m_hEvent);}
private:
  HANDLE m_hEvent;
};

//NET_BLOCK_SIZE : We can define NET_BLOCK_SIZE to any positive number
//Why I chose 4096-64 is based on that the PerIoData structure could
//be placed in a single memory page
const int NET_BLOCK_SIZE=4096-64;

enum NET_OPTYPE;
struct PerIoData
{
  // These fields are used by the implementation 
  // of NetIOCP... classes
  OVERLAPPED overlapped;
  WSABUF databuf;
  NET_OPTYPE op_type;
  SOCKET sock;

  // These fields can be used by the classes' users
  int len;
  char data[NET_BLOCK_SIZE];
};

class NetIOCPBase
{
public:
  NetIOCPBase();
  virtual ~NetIOCPBase();
  void start();
  void stop();
  void runloop();
  void senddata(SOCKET s,PerIoData *iodata);
  void close(SOCKET s);
protected:
  virtual void net_open_handler(SOCKET s)=0;
  virtual void net_closed_handler(SOCKET s)=0;
  virtual void net_data_handler(PerIoData *data)=0;
  virtual void start_run(){}
  virtual void stop_run(){}
  HANDLE miocp;
private:
  static unsigned int __stdcall completion_port_worker_thread(void *cookie);
  static int ref;
  void worker_func();

  void aio_send(SOCKET s,PerIoData *iodata);
  void aio_recv(SOCKET s,PerIoData *iodata);
  void aio_resend(PerIoData *iodata,int lastlen);
  void wkshutdown();
  
  vector<HANDLE> mwthread;
  bool started;

  bool create_sendqueue(SOCKET s);
  bool delete_sendqueue(SOCKET s);
  struct Channel
  {
    SOCKET sock;
    bool busy;
    list<PerIoData *> sendqueue;
  };
  map<SOCKET,Channel *> mmsend_pool;
  UserMutex mmsend_pool_mutex;

  //worker發送到主線程的通告(網絡事件)
  enum NET_EVENT
  {
    NE_SOCKNEW,    //新socket連接
    NE_SOCKCLOSED, //socket已經被關閉
    NE_DATARECVED, //收到數據
  };
  struct NetEvent
  {
    NET_EVENT event;
    PerIoData *iodata;
  };
  list<NetEvent> mnequeue;
  UserMutex mnequeue_mutex;
  list<NetEvent> mnequeue_main;
  void post_netevent(const NetEvent &ne)
  {
    Locker lock(&mnequeue_mutex);
    mnequeue.push_back(ne);
  }
  void recv_allnetevents()
  {
    Locker lock(&mnequeue_mutex);
    mnequeue_main.splice(mnequeue_main.end(),mnequeue);
  }
  bool peek_netevent(NetEvent *ne)
  {
    if(!mnequeue_main.empty())
    {
      *ne=mnequeue_main.front();
      mnequeue_main.pop_front();
      return true;
    }
    return false;
  }
};

/**
  class NetIOCPServer
  The basic server network data transfer class
  To use it you just 
   1  Inherit NetIOCPServer of your own class like
      class NetIOCPTestServer:public NetIOCPServer
   2  And rewrite your own pure virtual functions
      net_open_handler   //when new client come this function will be called
      net_closed_handler //when client has been closed this function will be called
      net_data_handler   //when data arrived this function will be called
   3  And call the framework:
      //...
      NetIOCPTestServer *server=new NetIOCPTestServer(listenport);
      server->start();
      //the main loop
      while(1)
      {
        //...
        server->runloop();
      }
      delete server;
   4  When you want to send data to somewhere
      first prepare your data,like
      PerIodata *iodata=new PerIoData;
      iodata->len=yourlen;
      memcpy(iodata->data,yourdata);
      then send it
      server->senddata(destsocket,iodata);
   5  When you want to close some client socket call
      server->close(clientsocket);
      Do not call the system function closesocket()
      directly,otherwise the iocp can not cleanup 
      the resources
*/
class NetIOCPServer:public NetIOCPBase
{
public:
  explicit NetIOCPServer(unsigned short port);
  ~NetIOCPServer();
protected:
  virtual void net_open_handler(SOCKET s)=0;
  virtual void net_closed_handler(SOCKET s)=0;
  virtual void net_data_handler(PerIoData *data)=0;
private:
  static unsigned int __stdcall completion_port_accept_thread(void *cookie);
  void accept_func();
  void start_run();
  void stop_run();

  unsigned short mport;
  HANDLE mathread;
  SOCKET mserver;
};

/**
  class NetIOCPClient
  the client counterpart of NetIOCPServer
  the only different is 
    You call connect to connect some server
*/
class NetIOCPClient:public NetIOCPBase
{
public:
  bool connect(const char *dotip,unsigned short port,SOCKET *s);
protected:
  virtual void net_open_handler(SOCKET s)=0;
  virtual void net_closed_handler(SOCKET s)=0;
  virtual void net_data_handler(PerIoData *data)=0;
};

/**
  class MsgIOCPServer and MsgIOCPClient
  The class create a find the message boundary
  we commonly inherit this class

  Network message format is
  datalen data datalen data...
  
  there is no space between messages or 
  between (datalen and data) 
  
  "datalen" indicate the message size
  That means the size of "data" is datalen
*/

// message structure
// We can define NET_MESSAGE_SIZE to any positive number;
//const int NET_MESSAGE_SIZE=4096-32;
//struct NetMessage
//{
//  int datalen;
//  char data[NET_MESSAGE_SIZE];
//};

struct MsgData
{
  int recv_lenlen;
  int recv_datalen;
  unsigned short len;
  NetMessage *msg;
};
template<class T>
class MsgIOCP:public T
{
public:
  explicit MsgIOCP(unsigned short port)
    :T(port)
  {
  }
  MsgIOCP(){}
  void sendmessage(SOCKET s,NetMessage *msg);
protected:
  virtual void msg_open_handler(SOCKET s)=0;
  virtual void msg_closed_handler(SOCKET s)=0;
  virtual void msg_message_handler(SOCKET s,NetMessage *msg)=0;
  virtual void msg_illegal_handler(SOCKET s,int msglen)=0;
private:
  void net_open_handler(SOCKET s);
  void net_closed_handler(SOCKET s);
  void net_data_handler(PerIoData *iodata);
  map<SOCKET,MsgData> mrecvpot;
  typedef map<SOCKET,MsgData>::iterator MapPotIter;
};

//
// We call this function to send a message
// the should neither be access nor be deleted 
// while after you have called the function 
//
template<class T>
void MsgIOCP<T>::sendmessage(SOCKET s,NetMessage *msg)
{
  assert(msg->datalen<=NET_MESSAGE_SIZE&&msg->datalen>0);

  //message head
  int head_block_num=(sizeof(unsigned short)-1)/NET_BLOCK_SIZE+1;
  unsigned short len=(unsigned short)msg->datalen;
  for(int i=0;i<head_block_num-1;++i)
  {
    PerIoData *iodata=new PerIoData;
    iodata->len=NET_BLOCK_SIZE;
    memcpy(iodata->data,(char *)&len+i*NET_BLOCK_SIZE,NET_BLOCK_SIZE);
    senddata(s,iodata);
  }
  PerIoData *iodata=new PerIoData;
  iodata->len=sizeof(unsigned short)-i*NET_BLOCK_SIZE;
  assert(iodata->len>0&&iodata->len<=NET_BLOCK_SIZE);
  memcpy(iodata->data,(char *)&len+i*NET_BLOCK_SIZE,iodata->len);
  if(iodata->len==NET_BLOCK_SIZE)
  {
    senddata(s,iodata);
    iodata=new PerIoData;
    iodata->len=0;
  }
  if(msg->datalen<=NET_BLOCK_SIZE-iodata->len)
  {
    memcpy(iodata->data+iodata->len,msg->data,msg->datalen);
    iodata->len+=msg->datalen;
    senddata(s,iodata);
    delete msg;
    return;
  }

  int new_block_num=(msg->datalen-(NET_BLOCK_SIZE-iodata->len)-1)/NET_BLOCK_SIZE+1;
  memcpy(iodata->data+iodata->len,msg->data,NET_BLOCK_SIZE-iodata->len);
  int msgdata_index=NET_BLOCK_SIZE-iodata->len;
  iodata->len=NET_BLOCK_SIZE;
  senddata(s,iodata);
  for(int i=0;i<new_block_num-1;++i)
  {
    iodata=new PerIoData;
    iodata->len=NET_BLOCK_SIZE;
    assert(msgdata_index+NET_BLOCK_SIZE<NET_MESSAGE_SIZE);
    memcpy(iodata->data,msg->data+msgdata_index,NET_BLOCK_SIZE);
    senddata(s,iodata);
    msgdata_index+=NET_BLOCK_SIZE;
  }
  assert(msgdata_index<NET_MESSAGE_SIZE);
  iodata=new PerIoData;
  iodata->len=msg->datalen-msgdata_index;
  assert(iodata->len>0);
  memcpy(iodata->data,msg->data+msgdata_index,iodata->len);
  senddata(s,iodata);
  delete msg;
}

template<class T>
void MsgIOCP<T>::net_open_handler(SOCKET s)
{
  pair<MapPotIter,bool> ret;
  MsgData data;
  data.recv_lenlen=0;
  data.recv_datalen=0;
  data.len=0;
  data.msg=new NetMessage;
  ret=mrecvpot.insert(make_pair(s,data));
  if(!ret.second)
  {
    assert(0);
    MapPotIter iter;
    iter=mrecvpot.find(s);
    iter->second.recv_lenlen=0;
    iter->second.recv_datalen=0;
    iter->second.len=0;
  }
  msg_open_handler(s);
}
template<class T>
void MsgIOCP<T>::net_closed_handler(SOCKET s)
{
  MapPotIter iter;
  iter=mrecvpot.find(s);
  if(mrecvpot.end()==iter)
  {
    assert(0);
  }
  else
  {
    delete iter->second.msg;
    mrecvpot.erase(iter);
  }
  msg_closed_handler(s);
}
template<class T>
void MsgIOCP<T>::net_data_handler(PerIoData *iodata)
{
  assert(iodata->len>0&&iodata->len<=NET_BLOCK_SIZE);
  MapPotIter iter;
  iter=mrecvpot.find(iodata->sock);
  if(mrecvpot.end()==iter)
  {
    assert(0);
    MsgData data;
    data.recv_datalen=0;
    data.recv_lenlen=0;
    data.len=0;
    data.msg=new NetMessage;
    mrecvpot.insert(make_pair(iodata->sock,data));
  }
  MsgData *pot=&iter->second;
  int iodata_index=0;
  while(iodata_index<iodata->len)
  {
    //message head
    if(pot->recv_lenlen<sizeof(unsigned short))
    {
      int copy_len=min(iodata->len-iodata_index,sizeof(unsigned short)-pot->recv_lenlen);
      memcpy((char *)&pot->len+pot->recv_lenlen,iodata->data+iodata_index,copy_len);
      pot->recv_lenlen+=copy_len;
      iodata_index+=copy_len;
      if(iodata_index==iodata->len)
      {
        break;
      }
    }
    //illegal message
    if(pot->len<=0||pot->len>NET_MESSAGE_SIZE)
    {
      msg_illegal_handler(iodata->sock,pot->len);
      pot->recv_lenlen=0;
      pot->recv_datalen=0;
      pot->len=0;
      break;
    }
    //message body
    if(pot->recv_datalen<pot->len)
    {
      int copy_len=min(iodata->len-iodata_index,pot->len-pot->recv_datalen);
      memcpy(pot->msg->data+pot->recv_datalen,iodata->data+iodata_index,copy_len);
      pot->recv_datalen+=copy_len;
      iodata_index+=copy_len;
      if(pot->recv_datalen==pot->len)
      {
        pot->msg->datalen=pot->len;
        pot->recv_lenlen=0;
        pot->recv_datalen=0;
        pot->len=0;
        msg_message_handler(iodata->sock,pot->msg);
      }
    }
  }
}

typedef MsgIOCP<NetIOCPServer> MsgIOCPServer;
typedef MsgIOCP<NetIOCPClient> MsgIOCPClient;

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美成人a在线| 欧美最猛性xxxxx直播| 三级成人在线视频| 亚洲成人精品一区二区| 亚洲精品视频在线看| 国产精品午夜在线| 亚洲婷婷在线视频| 一区二区在线观看免费视频播放 | 中文字幕亚洲电影| 1区2区3区欧美| 一区二区三区精品视频在线| 亚洲一区免费在线观看| 首页国产欧美日韩丝袜| 六月婷婷色综合| 国产乱人伦偷精品视频不卡| 波多野结衣视频一区| 99久久精品国产麻豆演员表| 91免费在线视频观看| 欧美最新大片在线看| 日韩三级中文字幕| 日本一区二区成人在线| 亚洲在线免费播放| 久久国产综合精品| 91在线小视频| 91精品国产aⅴ一区二区| 国产午夜亚洲精品理论片色戒| 最近日韩中文字幕| 蜜桃久久久久久| 99久久精品国产网站| 欧美一级黄色录像| 国产精品电影院| 麻豆国产一区二区| 91美女片黄在线观看| 91精品福利在线一区二区三区| 久久久久国产一区二区三区四区| 亚洲天堂av老司机| 麻豆91在线播放免费| 91蝌蚪porny成人天涯| 91精品国产91久久久久久最新毛片| 久久久欧美精品sm网站 | 欧美日韩一区视频| 国产欧美日韩综合| 日本午夜精品视频在线观看| 福利91精品一区二区三区| 欧美日韩一区二区三区在线看 | 北条麻妃国产九九精品视频| 欧美日韩一区高清| 亚洲欧洲综合另类| 国产一区二区免费看| 欧美久久久久久蜜桃| 国产精品国产三级国产aⅴ入口 | 亚洲成人av中文| 99精品视频在线播放观看| 精品福利一二区| 亚洲成av人片一区二区梦乃| 成人小视频免费在线观看| 精品国产三级a在线观看| 日韩精品乱码av一区二区| 色94色欧美sute亚洲线路一ni| 国产日韩欧美一区二区三区乱码| 美女诱惑一区二区| 欧美另类变人与禽xxxxx| 综合激情网...| 成人app网站| 欧美国产日韩亚洲一区| 国产成人99久久亚洲综合精品| 欧美刺激脚交jootjob| 日韩电影一区二区三区四区| 欧美影院一区二区三区| 亚洲综合图片区| 色嗨嗨av一区二区三区| 亚洲理论在线观看| 欧美亚洲综合另类| 五月综合激情网| 欧美一区二区精品久久911| 日韩不卡在线观看日韩不卡视频| 欧美日韩大陆一区二区| 日韩国产在线一| 日韩免费观看高清完整版在线观看| 三级一区在线视频先锋| 精品人伦一区二区色婷婷| 日本伊人精品一区二区三区观看方式 | 精品综合久久久久久8888| 91精品国产一区二区| 理论电影国产精品| 久久精品人人做人人综合| 韩国精品主播一区二区在线观看| 精品国产凹凸成av人导航| 国产成人高清视频| 中文字幕中文字幕一区| 一本到不卡免费一区二区| 午夜av一区二区三区| 欧美变态tickle挠乳网站| 国产iv一区二区三区| 中文字幕一区三区| 欧美精品九九99久久| 极品少妇xxxx精品少妇偷拍 | 亚洲图片另类小说| 欧美日韩和欧美的一区二区| 日韩avvvv在线播放| 国产欧美日韩精品在线| 99久久精品国产精品久久| 亚洲h在线观看| 国产网红主播福利一区二区| 91欧美激情一区二区三区成人| 亚洲一区二区黄色| 久久久精品日韩欧美| 色哦色哦哦色天天综合| 久久精品国内一区二区三区| 国产精品色哟哟网站| 欧美性生活影院| 国模无码大尺度一区二区三区| 中文字幕一区二区三区视频 | 成人av在线网| 日韩黄色片在线观看| 日本一区二区免费在线观看视频 | 视频一区视频二区中文字幕| 欧美激情一二三区| 56国语精品自产拍在线观看| 成人免费视频免费观看| 日本在线不卡视频一二三区| 亚洲欧洲制服丝袜| 国产亚洲va综合人人澡精品| 欧美日韩亚洲国产综合| 波多野结衣中文一区| 精品一区二区在线免费观看| 一区二区三区欧美日韩| 国产三级精品视频| 日韩一区二区三区在线观看| 91久久奴性调教| 不卡一区在线观看| 国产麻豆欧美日韩一区| 青青草原综合久久大伊人精品 | 欧美挠脚心视频网站| 91丨九色丨蝌蚪丨老版| 国产传媒日韩欧美成人| 久久国产精品第一页| 日本中文字幕一区二区视频| 一区二区欧美精品| 亚洲色图.com| 日韩美女视频19| 中文字幕在线不卡视频| 欧美极品另类videosde| 精品久久久久久综合日本欧美| 欧美日韩精品一区二区| 欧美中文字幕一区| 欧美网站一区二区| 日本大香伊一区二区三区| 91免费观看视频| 91色在线porny| 日本韩国欧美在线| 在线观看av不卡| 欧美日韩一区二区三区四区 | 狠狠色丁香久久婷婷综| 青青草原综合久久大伊人精品优势| 亚洲地区一二三色| 午夜精品成人在线| 免费日本视频一区| 久久99精品国产麻豆不卡| 国产一区二区三区久久悠悠色av| 久久超碰97人人做人人爱| 韩国视频一区二区| a在线播放不卡| 色综合天天综合狠狠| 欧美性受xxxx黑人xyx| 欧美日韩国产一级| 欧美不卡视频一区| 欧美激情一区二区在线| 亚洲视频你懂的| 天天综合色天天综合| 另类小说欧美激情| 成人在线一区二区三区| 99久久精品免费看| 欧美精品丝袜中出| 久久网站最新地址| 最新高清无码专区| 日韩高清一区二区| 成人av午夜影院| 欧美日韩精品欧美日韩精品一| 日韩精品一区二区三区四区| 欧美激情艳妇裸体舞| 一区二区三区国产豹纹内裤在线| 日韩中文字幕麻豆| 欧美午夜精品一区二区三区| 欧美精品高清视频| 国产欧美一区二区精品性| 亚洲综合在线免费观看| 久久66热re国产| 色妹子一区二区| 久久久久久亚洲综合| 亚洲精品中文在线观看| 蜜臀av一级做a爰片久久| proumb性欧美在线观看| 91精品国产综合久久香蕉的特点 | 中文字幕精品一区| 天天色天天爱天天射综合| 不卡的电影网站| 精品国产一二三| 水蜜桃久久夜色精品一区的特点| 国产精品一线二线三线精华|