谁能提供一段稳定的完成端口源代码? ( 积分: 300 )

  • 主题发起人 主题发起人 muhx
  • 开始时间 开始时间
M

muhx

Unregistered / Unconfirmed
GUEST, unregistred user!
如题
大家有没有写过比较稳定的完成端口类或者程序
贴点代码学习一下,谢谢
 
要学习的话,下面这个例子比较简单但比较清晰

//////////////////////////////////////////////////////////
// initsock.h文件

#include <winsock2.h>
#pragma comment(lib, &quot;WS2_32&quot;) // 链接到WS2_32.lib

class CInitSock
{
public:
CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
{
// 初始化WS2_32.dll
WSADATA wsaData;
WORD sockVersion = MAKEWORD(minorVer, majorVer);
if(::WSAStartup(sockVersion, &amp;wsaData) != 0)
{
exit(0);
}
}
~CInitSock()
{
::WSACleanup();
}
};


/////////////////////////////////////////////////
// IOCPDemo.cpp文件 调试通过


#include &quot;../common/initsock.h&quot;
#include <stdio.h>
#include <windows.h>

// 初始化Winsock库
CInitSock theSock;

#define BUFFER_SIZE 1024

typedef struct _PER_HANDLE_DATA // per-handle数据
{
SOCKET s; // 对应的套节字句柄
sockaddr_in addr; // 客户方地址
} PER_HANDLE_DATA, *PPER_HANDLE_DATA;


typedef struct _PER_IO_DATA // per-I/O数据
{
// 重叠结构
OVERLAPPED ol;
char buf[BUFFER_SIZE]; // 数据缓冲区

int nOperationType; // 操作类型
#define OP_READ 1
#define OP_WRITE 2
#define OP_ACCEPT 3
} PER_IO_DATA, *PPER_IO_DATA;


DWORD WINAPI ServerThread(LPVOID lpParam)
{
// 得到完成端口对象句柄
HANDLE hCompletion = (HANDLE)lpParam;

DWORD dwTrans;
PPER_HANDLE_DATA pPerHandle;
PPER_IO_DATA pPerIO;
while(TRUE)
{
// 在关联到此完成端口的所有套节字上等待I/O完成
BOOL bOK = ::GetQueuedCompletionStatus(hCompletion,
&amp;dwTrans, (LPDWORD)&amp;pPerHandle, (LPOVERLAPPED*)&amp;pPerIO, WSA_INFINITE);
if(!bOK) // 在此套节字上有错误发生
{
::closesocket(pPerHandle->s);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}

if(dwTrans == 0 &amp;&amp; // 套节字被对方关闭
(pPerIO->nOperationType == OP_READ || pPerIO->nOperationType == OP_WRITE))

{
::closesocket(pPerHandle->s);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}

switch(pPerIO->nOperationType) // 通过per-I/O数据中的nOperationType域查看什么I/O请求完成了
{
case OP_READ: // 完成一个接收请求
{
pPerIO->buf[dwTrans] = '/0';
printf(pPerIO -> buf);

// 继续投递接收I/O请求
WSABUF buf;
buf.buf = pPerIO->buf ;
buf.len = BUFFER_SIZE;
pPerIO->nOperationType = OP_READ;

DWORD nFlags = 0;
::WSARecv(pPerHandle->s, &amp;buf, 1, &amp;dwTrans, &amp;nFlags, &amp;pPerIO->ol, NULL);
}
break;
case OP_WRITE: // 本例中没有投递这些类型的I/O请求
case OP_ACCEPT:
break;
}
}
return 0;
}


void main()
{
int nPort = 4567;
// 创建完成端口对象,创建工作线程处理完成端口对象中事件
HANDLE hCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
::CreateThread(NULL, 0, ServerThread, (LPVOID)hCompletion, 0, 0);

// 创建监听套节字,绑定到本地地址,开始监听
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN si;
si.sin_family = AF_INET;
si.sin_port = ::ntohs(nPort);
si.sin_addr.S_un.S_addr = INADDR_ANY;
::bind(sListen, (sockaddr*)&amp;si, sizeof(si));
::listen(sListen, 5);

// 循环处理到来的连接
while(TRUE)
{
// 等待接受未决的连接请求
SOCKADDR_IN saRemote;
int nRemoteLen = sizeof(saRemote);
SOCKET sNew = ::accept(sListen, (sockaddr*)&amp;saRemote, &amp;nRemoteLen);

// 接受到新连接之后,为它创建一个per-handle数据,并将它们关联到完成端口对象。
PPER_HANDLE_DATA pPerHandle =
(PPER_HANDLE_DATA)::GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));
pPerHandle->s = sNew;
memcpy(&amp;pPerHandle->addr, &amp;saRemote, nRemoteLen);
::CreateIoCompletionPort((HANDLE)pPerHandle->s, hCompletion, (DWORD)pPerHandle, 0);

// 投递一个接收请求
PPER_IO_DATA pPerIO = (PPER_IO_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
pPerIO->nOperationType = OP_READ;
WSABUF buf;
buf.buf = pPerIO->buf;
buf.len = BUFFER_SIZE;
DWORD dwRecv;
DWORD dwFlags = 0;
::WSARecv(pPerHandle->s, &amp;buf, 1, &amp;dwRecv, &amp;dwFlags, &amp;pPerIO->ol, NULL);
}
}
 
谢谢楼上的代码
我更关心的不是怎样使用,而是怎样可靠的使用
大家有什么建议也可以说
分不够可以另外开贴放分,谢谢

如果真的使用过IOCP,可能会遇到很多问题
大家把遇到的问题和解决的办法以及注意事项提供一下
大家互相学习一下
 
看来大家都在忙着听总理的记者招待会
没空回答问题了:)
 
惭愧,会错意了,可惜偶也是个菜鸟没法给你提供商用的代码:(
 
哇,这么长的代码,真佩服,希望我也能早日达到他(她)的水平,呵呵
 
谢谢52free
也不是需要商用的代码
只是希望大家在这里互相谈一下经验教训
都尽快提高少走弯路
 
我的就是线程池和内存池。 呵呵
 
看来大家用的都比较少
可能这方面的专家都去了盛大了:)
 
可以搜到一份bakubaku大侠原来写的仿Tserversocket架构的完成端口对象单元,原来的帖子里都有。
 
是啊! 专家的都在盛大那了! 在网上找原码都是书上就有的。 楼主难啊
想走捷径估计很难,还是老实地去研究去多写了。
 
看来大家对这个主题没有什么兴趣:(
 
建议楼主还是提一些具体的问题吧,说不定用过的人可以帮到你。
另外也可以参考一下这个:
http://www.delphibbs.com/keylife/iblog_show.asp?xid=23237
 
有兴趣,却没有测试的条件
我这儿有个的C++的ICOP服务例子,我个人觉得应该还行,基本上该考虑的也都考虑了
采用的线程池和读队列序号校验
你要的话留email,我发代码给你,你可以改成delphi的,我也想可是现在没时间:(
我们可以讨论讨论
 
我的信箱是muhx1981@126.com
发给我一份吧
我试着把他改成Delphi的

另外希望有对IOCP有兴趣的朋友,我们可以一起讨论作出一个通用的IOPC服务类来

另外谢谢xianjun的提示

另外To shangshang,我没有找到bakubaku的例子,如果你找到了烦请将网址告诉我一下,谢谢
 
我觉得作稳定的SERVER,首先将SERVER与逻辑处理的中介作好。将SERVER、中介、处理分别独立开来,这样,不至于各模块间的某些效率影响通讯。
而LZ只是说SERVER的通讯层,我觉得是先将内存池处理好再说,其它的次要考虑。
 
IOCP的框架结构,一般来说结构都大同小异,网上C,DELPHI的都差不多。但内存管理及一些收发细节处理才是细微操作,我觉得这些才是有价值的东西。
 
已发,查收
 
谢谢errorcode,我的看法和你一样
IOPC的框架应该都差不多,细节处理才是最主要的
我发这个帖子的用意也是大家在使用中遇到什么问题和解决的方法大家谈一下自己的看法
争取在我们的实际开发中少犯同样的错误

另外,对于效率也希望得到一些有意的提示,谢谢。

谢谢52free兄,邮件我已经收到
为了表明我发帖的诚意,我今天或者明天将这个帖子结掉,送分
然后再开一个300分的帖子大家继续讨论

谢谢楼上的各位
 
iocp应该是适合大并发但短寿命的应用
如果业务逻辑本身比较耗时我想用阻塞的多线程模块可能会更好,但是这又不能适应大量的并发操作
要从中取得平衡也是很难的
 
后退
顶部