首页
社区
课程
招聘
[原创]自己对异步IO完成端口的体会 有些不足大家帮忙说下
发表于: 2011-5-17 16:20 8744

[原创]自己对异步IO完成端口的体会 有些不足大家帮忙说下

2011-5-17 16:20
8744
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

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 107
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
体会在????
2011-5-17 16:24
0
雪    币: 111
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
1、为什么WSARecv(.., 1, ...); 因为代码中写的是每次接收1bytes
2、粗略看了一下你的大体代码,用LoadRunner测试一下,服务端程序应该会崩
3、建议处理一下粘包以及封包的校验,另外可以考虑做内存池之类的管理下,还有连接超时检测等等
2011-5-17 17:01
0
雪    币: 40
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
好的 不过我那些内存处理的暂时弄掉等下在交流 我粗略的省略掉了
2011-5-17 17:10
0
雪    币: 40
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
不礼貌的说一句 我刚才请教高手
你对一个字节的看法也是错的
麻烦请看下MSDN  我只是建议 谢谢你的上面的几个回答 对我很有用

不过能说下在哪里检测连接超时吗   还有内存池管理是否就是我自定义的那个结构 new CClientContext 管理和分配这个
2011-5-17 18:47
0
雪    币: 111
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
不好意思,看错WSARecv的结构了,和recv记混了,是BufferCount,我刚才说的每次只接受1bytes是有些东西是这么做的,比如某飞信群发,这样做可以解决部分粘包问题,但是数据包大的话就会影响性能了。
建议看下内存池概念吧,申请释放多了内存不稳定,影响性能,可以考虑做成内存池,没必要每次都delete
IOCP这东西写出来都差不多,体现在细节上的处理,才会提高并发量。
建议装一个LoadRunner测试一下。

还有,代码就别老编辑掉了,免得别人看回帖发现与1楼的代码不符,造成误解。
2011-5-17 23:01
0
雪    币: 111
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
连接超时的话检测方法很多,可以单独开个线程来处理一下,不过处理手法上要细腻一点,别让检测线程占用太多系统资源,否则性能会有影响。
2011-5-17 23:13
0
雪    币: 168
活跃值: (152)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
8
http://www.codeproject.com/KB/IP/SimpleIOCPApp.aspx


人家说的好像挺详细的呀~
2011-7-3 19:43
0
雪    币: 14
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这种通信框架有没有比较经典的代码可读的
2011-7-4 08:42
0
雪    币: 190
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
m_pwbuf->buf = m_szBuffer;  //这句话的意思是不是说 将m_szBuffer 指针给了buf
       m_pwbuf->len = MAX_BUFFER_LEN;    //也就是说 实际上WSABUF里的数组指针指向的是m_szBuffer 实际接收的数据是 在m_szBuffer数组里 问题

微软决定要WSABUF为缓冲区参数,buf要指向一块有效内存 因为 m_szBuffer 的生命周期和 m_pwbuf是一致的 所以那样。。

if (true == AssociateWithIOCP(pClientContext))  //请问这个关联操作会触发OP_READ 完成操作事件吗   问题1 ?????????
据我猜测是不会出发读操作的

    //这里是接收一个字节 搞不懂为啥是一个字节 为啥 要接收难道我发送不行吗  问题2 ?????????
      int nBytesRecv = WSARecv(pClientContext->GetSocket(), p_wbuf, 1,&dwBytes, &dwFlags, p_ol, NULL);
这里是投递一个读的IOCP请求到队列中 也就是说有数据会触发你上面说的OP_READ操作(但是看你代码貌似是设置OP_WRITE

   pClientContext->SetOpCode(OP_WRITE);  //如果发送的数据 大于总共要发送的 到这一步 设置开始接收数据 触发下一个事件
              //为什么 没有没有关于WSARecv的 而且有也只有一个字节 难道接收只接收一个字节吗    问题 3?????????
          pClientContext->ResetWSABUF();  //清空WSABUF结构      
不是一个字节是一个WSABUF

pClientContext->GetBuffer(szBuffer);  //接收到的字节 怎么接收的没说啊 为啥只接收了一个字节 接受一个缓冲区为啥就能打印不继续接收 难道 继续接收应该设置下面那个标志为 OP_WRITE   //问题4??????

为什么只有一个字节我也不知道,不过你strcpy是很不负责任很危险的做法 小心堆栈溢出, 本次IO有多少字节不是 print(%s)说了算 是 dwBytesTransfered 说了算
是内核给你完成的,完成了给你的队列投递一个信息,然后你在Get出来, 和消息队列有一点点类似
继续接受关键是投递WSARecv操作到队列

记得点一下致谢
2011-7-4 22:15
0
雪    币: 146
活跃值: (33)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
我是手机党,来膜拜十楼的
不作粘包处理和封包解析还是不行滴
2011-7-5 01:21
0
雪    币: 190
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
不好意思哈,最近有点忙,改天一起吃饭
2011-7-8 21:03
0
游客
登录 | 注册 方可回帖
返回
//