- 浏览: 319484 次
最新评论
-
riki:
D 语言学习交流群 264617728, 欢迎加入
D语言真相 The Case for D(1-5) -
exploder:
请教,如果使用D2进行wxD编译呢?
编译WxD0.16 -
blue_halo:
那如何解决呢????????
不能每次都用别的打开存成utf- ...
pyDev 中输入中文问题 -
funxue:
请教楼主
Error: undefined identifie ...
D语言版本的华容道 -
litsen:
在配置ms sqlserver的过程中遇到些问题,从Googl ...
安全第一,在sql server和client之间配置ssl连接
在WindowsNT平台上,最具有伸缩性和吞吐量的网络服务器程序都使用了完成端口。为了在D中使用完成端口,我写了这个简单的例子。希望大家指正!
在DMD1.020-1.022,WindowsXP,编译测试通过。
没有使用std.socket,因为std里面的socket实现不能使用重叠IO。
D 代码
- // D Program Language IOCP
- // write by ideage@gmail.com
- // complie: dmd ic ws2_32.lib
- import std.c.windows.windows, std.c.windows.winsock;
- import std.string, std.stdint, std.c.string, std.c.stdlib;
- import std.stdio;
- import std.thread;
- alias HANDLE WSAEVENT;
- alias OVERLAPPED WSAOVERLAPPED;
- alias OVERLAPPED* LPWSAOVERLAPPED;
- alias OVERLAPPED* POVERLAPPED, LPOVERLAPPED;
- struct GUID {
- align(1):
- DWORD Data1;
- WORD Data2;
- WORD Data3;
- BYTE Data4[8];
- }
- struct WSAPROTOCOLCHAIN {
- int ChainLen;
- DWORD[7] ChainEntries;
- }
- alias WSAPROTOCOLCHAIN* LPWSAPROTOCOLCHAIN;
- const WSAPROTOCOL_LEN = 255;
- const ERROR_IO_PENDING = 997;
- struct WSAPROTOCOL_INFOW {
- DWORD dwServiceFlags1;
- DWORD dwServiceFlags2;
- DWORD dwServiceFlags3;
- DWORD dwServiceFlags4;
- DWORD dwProviderFlags;
- GUID ProviderId;
- DWORD dwCatalogEntryId;
- WSAPROTOCOLCHAIN ProtocolChain;
- int iVersion;
- int iAddressFamily;
- int iMaxSockAddr;
- int iMinSockAddr;
- int iSocketType;
- int iProtocol;
- int iProtocolMaxOffset;
- int iNetworkByteOrder;
- int iSecurityScheme;
- DWORD dwMessageSize;
- DWORD dwProviderReserved;
- WCHAR[WSAPROTOCOL_LEN+1] szProtocol;
- }
- alias WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFOW;
- const WSA_FLAG_OVERLAPPED = 0x01;
- struct WSABUF {
- uint len;
- char* buf;
- }
- struct SOCKADDR {
- ushort sa_family;
- char[14] sa_data;
- }
- alias SOCKADDR* PSOCKADDR, LPSOCKADDR;
- alias WSABUF* LPWSABUF;
- alias uint GROUP;
- extern(Windows)
- {
- alias void function(DWORD, DWORD, LPWSAOVERLAPPED, DWORD) LPWSAOVERLAPPED_COMPLETION_ROUTINE;
- SOCKET WSASocketW(int, int, int, LPWSAPROTOCOL_INFOW, GROUP, DWORD);
- bool GetQueuedCompletionStatus(HANDLE, PDWORD, PDWORD, LPOVERLAPPED*, DWORD);
- HANDLE CreateIoCompletionPort(HANDLE, HANDLE, DWORD, DWORD);
- int WSASend(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
- int WSARecv(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
- }
- alias WSASocketW WSASocket;
- // Maximum Buffer Size
- const int BUFFERSIZE = 128;
- enum IO_OPERATION
- { ACCEPT,READ,WRITE };
- struct PIO_DATA
- {
- WSAOVERLAPPED ol;
- char Buffer[BUFFERSIZE];
- WSABUF wsabuf;
- int nTotalBytes;
- int nSentBytes;
- IO_OPERATION opCode;
- SOCKET activeSocket;
- }
- int max_ThreadCount;
- HANDLE iocpHandle = INVALID_HANDLE_VALUE;
- SOCKET serverSock;
- int WorkerThread (void * context)
- {
- LPWSAOVERLAPPED lpol = null;
- PIO_DATA* lpIOContext = null;
- WSABUF buffSend;
- uint dwRecvNumBytes = 0;
- uint dwSendNumBytes = 0;
- uint dwFlags = 0;
- uint dwIoSize = 0;
- bool bSuccess = false;
- int nRet = 0;
- while( 1 ) {
- void * lpCompletionKey = null;
- bSuccess = GetQueuedCompletionStatus(iocpHandle, &dwIoSize,cast(LPDWORD)&lpCompletionKey,cast(LPOVERLAPPED *)&lpol, INFINITE);
- if( !bSuccess )
- {
- writefln("GetQueuedCompletionStatus() failed: %s.",GetLastError());
- break;
- }
- lpIOContext = cast(PIO_DATA * )lpol;
- if(dwIoSize == 0) //socket closed?
- {
- writefln("ClientSocket Disconnect!" );
- closesocket(lpIOContext.activeSocket);
- // delete lpIOContext;
- continue;
- }
- if(lpIOContext.opCode == IO_OPERATION.READ) // a read operation complete
- {
- char[] s = "Echo:" ~ std.string.toString(lpIOContext.wsabuf.buf);
- lpIOContext.wsabuf.buf = std.string.toStringz(s);
- lpIOContext.nTotalBytes = lpIOContext.wsabuf.len;
- lpIOContext.nSentBytes = 0;
- lpIOContext.opCode = IO_OPERATION.WRITE;
- dwFlags = 0;
- nRet = WSASend(
- lpIOContext.activeSocket,
- &lpIOContext.wsabuf, 1, &dwSendNumBytes,
- dwFlags,
- &(lpIOContext.ol) , null);
- if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) )
- {
- writefln("1.WASSend Failed,Ret:%s." ,WSAGetLastError() );
- closesocket(lpIOContext.activeSocket);
- continue;
- }
- }
- else if(lpIOContext.opCode == IO_OPERATION.WRITE) //a write operation complete
- {
- lpIOContext.nSentBytes += dwIoSize;
- dwFlags = 0;
- if( lpIOContext.nSentBytes < lpIOContext.nTotalBytes ) {
- lpIOContext.opCode = IO_OPERATION.WRITE;
- // A Write operation has not completed yet, so post another
- // Write operation to post remaining data.
- buffSend.buf = lpIOContext.Buffer.ptr + lpIOContext.nSentBytes; //offset.
- buffSend.len = lpIOContext.nTotalBytes - lpIOContext.nSentBytes;
- nRet = WSASend (lpIOContext.activeSocket,
- &buffSend, 1, &dwSendNumBytes,
- dwFlags,
- &(lpIOContext.ol), null);
- if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
- writefln("2.WASSend Failed,Ret:%s.",WSAGetLastError());
- closesocket(lpIOContext.activeSocket);
- continue;
- }
- }
- else
- {
- // Write operation completed, so post Read operation.
- lpIOContext.opCode = IO_OPERATION.READ;
- dwRecvNumBytes = 0;
- dwFlags = 0;
- lpIOContext.wsabuf.buf = lpIOContext.Buffer.ptr,
- lpIOContext.ol.Internal = 0;
- lpIOContext.ol.InternalHigh = 0;
- lpIOContext.ol.Offset = 0;
- lpIOContext.ol.OffsetHigh = 0;
- lpIOContext.ol.hEvent = null;
- lpIOContext.wsabuf.len = BUFFERSIZE;
- nRet = WSARecv(
- lpIOContext.activeSocket,
- &lpIOContext.wsabuf, 1, &dwRecvNumBytes,
- &dwFlags,
- &lpIOContext.ol, null);
- if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
- writefln("1.WASRecv Failed,Ret:%s.",WSAGetLastError() );
- closesocket(lpIOContext.activeSocket);
- continue;
- }
- }
- }
- }
- return 0;
- }
- int main ()
- {
- { // Init winsock2.2
- WSADATA wsaData;
- int retVal = -1;
- if( (retVal = WSAStartup(0x2020, &wsaData)) != 0 ) {
- writefln("WSAStartup Failed,Ret: %s" ,retVal);
- return 1;
- }
- }
- writefln("WSAStartup Init OK!" );
- { //Create socket
- serverSock = WSASocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, null,0,WSA_FLAG_OVERLAPPED);
- if( serverSock == INVALID_SOCKET ) {
- writefln("Server Socket Creation Failed,Ret:%s." , WSAGetLastError() );
- return 1;
- }
- }
- writefln("Create socket OK!" );
- { //bind
- sockaddr_in service;
- service.sin_family = AF_INET;
- service.sin_addr.s_addr = htonl(INADDR_ANY);
- service.sin_port = htons(9001);
- int retVal = bind(serverSock,cast(sockaddr *)&service,service.sizeof);
- if( retVal == SOCKET_ERROR ) {
- writefln("Server Soket Bind Failed,Ret:%s." , WSAGetLastError() );;
- return 1;
- }
- }
- writefln("Binding ServerSocket OK!" );
- { //listen
- int retVal = listen(serverSock, 8);
- if( retVal == SOCKET_ERROR ) {
- writefln("Server Socket Listen Failed,Ret:%s." , WSAGetLastError() );;
- return 1;
- }
- }
- writefln("ServerSocket listen OK!" );
- //create iocp & binding serverSocket to iocp
- { // Create IOCP
- max_ThreadCount = 1 * 2;
- iocpHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE,null,0,max_ThreadCount);
- if (iocpHandle == null) {
- writefln("CreateIoCompletionPort() Failed,Ret:%s." , GetLastError() );
- return 1;
- }
- if (CreateIoCompletionPort(cast(HANDLE)serverSock,iocpHandle,0,0) == null){
- writefln("Binding Server Socket to IO Completion Port Failed,Ret:%s." , GetLastError() );
- return 1;
- }
- }
- writefln("Create IOCP & binding ServerSocket to IOCP OK!" );
- {
- Thread worker = new Thread(&WorkerThread, cast(void *)0);
- worker.start();
- }
- writefln("Create Worker threads OK, Waitting Client Connect..." );
- { //accept new connection
- while(1)
- {
- SOCKET clientsock = accept( serverSock, null, null );
- if(clientsock == SOCKET_ERROR) break;
- writefln("Client connected." );
- { //diable buffer to improve performance
- int nZero = 0;
- setsockopt(clientsock, SOL_SOCKET, SO_SNDBUF, cast(char *)&nZero, nZero.sizeof);
- }
- //binding ClientSocket to IOCP
- if (CreateIoCompletionPort(cast(HANDLE)clientsock,iocpHandle,0,0) == null){
- writefln("Binding Client Socket to IO Completion Port Failed,Ret:%s." , GetLastError() );
- closesocket(clientsock);
- }
- else {
- writefln("binding ClientSocket to IOCP OK!" );
- //post a recv request
- PIO_DATA data;
- data.opCode = IO_OPERATION.READ;
- data.nTotalBytes = 0;
- data.nSentBytes = 0;
- data.wsabuf.buf = data.Buffer.ptr;
- data.wsabuf.len = data.Buffer.sizeof;
- data.activeSocket = clientsock;
- uint dwRecvNumBytes=0,dwFlags=0;
- int nRet = WSARecv(clientsock,&data.wsabuf, 1, &dwRecvNumBytes,&dwFlags,&data.ol, null);
- if(nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
- writefln("3.WASRecv Failed,Ret:%s." , WSAGetLastError() );;
- closesocket(clientsock);
- //delete data;
- }
- writefln("Post a recv request IOCP OK!" );
- }
- }
- }
- //close & Cleanup
- closesocket(serverSock);
- WSACleanup();
- return 0;
- }
评论
9 楼
ahadf
2007-10-22
"iocp的使用例子(哪怕是C方式的)在dsource上都找不到一个,仅此一条ideage的做法就值得称道."
---不想抬杠,不过偶手边的资料有5,6本书上都有类似的。网上一搜IOCP更是一大把。也许写个boost.asio D 语言简化版本还比较有价值。
---不想抬杠,不过偶手边的资料有5,6本书上都有类似的。网上一搜IOCP更是一大把。也许写个boost.asio D 语言简化版本还比较有价值。
8 楼
h_rain
2007-10-22
不错了.都这个样子了,进行封装也很简单了.
如果需要一个好的封装,需要考虑一些方面:IOCP句柄与状态查询的封装;线程的完善处理("逻辑"暂停,启动...);Socket句柄的重叠IO操作封装等;
如果想要一个完整的封装,这些东西的处理其实还是很复杂的.
如果需要一个好的封装,需要考虑一些方面:IOCP句柄与状态查询的封装;线程的完善处理("逻辑"暂停,启动...);Socket句柄的重叠IO操作封装等;
如果想要一个完整的封装,这些东西的处理其实还是很复杂的.
7 楼
tomqyp
2007-10-22
iocp的使用例子(哪怕是C方式的)在dsource上都找不到一个,仅此一条ideage的做法就值得称道。
6 楼
ahadf
2007-10-22
偶还是要说,又没用到D的特性,又没用到D的库,用C不挺好,为啥还要用D写呢?演示?这种程序书上网上一抓一大把,学C的比学D的人多多了,直接copy下来看的人指不定还多些。
5 楼
ideage
2007-10-22
这个例子关键是演示了IOCP在D语言中的应用:过程,方法。
已经写的IOCP的类,用在公司的程序,不能公开
已经写的IOCP的类,用在公司的程序,不能公开
4 楼
dayn9
2007-10-22
这只能说是批着D马甲的C程序吧?
oldrev老大,这点我持有异议。D也应该是多范式的语言,不能只有OO,OB,GP,否则会损失潜在用户,SP范式恰恰是用户最大的群体。
oldrev老大,这点我持有异议。D也应该是多范式的语言,不能只有OO,OB,GP,否则会损失潜在用户,SP范式恰恰是用户最大的群体。
3 楼
ahadf
2007-10-21
我还以为是一个IOCP的类。。。
2 楼
oldrev
2007-10-21
这只能说是批着D马甲的C程序吧?
1 楼
tomqyp
2007-10-20
收藏~
发表评论
-
最近抽空翻译了D语言实用入门教程
2018-04-20 10:42 829最近抽空翻译了D语言实用入门教程 地址在Github,供初 ... -
编译WxD0.16
2011-09-27 18:09 1662wx我在Python环境下用了 ... -
简单看了下DGui
2011-09-26 10:39 2189很久没有写代码了。。。。 怀念往日不如今天行动。生疏了 ... -
支持中文录入的harmonia
2010-08-16 22:40 1003harmonia界面很方便,发现不能录入中文.Patch一下. ... -
控制台得到密码不回显
2009-09-18 22:37 1219看到坛子有人问“在D或C下如何实现输入单个字符不回显?可能的应 ... -
D资源文件调用
2009-08-09 01:36 1018终于成功了。 资源文件太可爱,竟然可以如此。按名称进行 ... -
The Case for D中英文版PDF下载
2009-06-19 10:27 1360The Case for D 在网站上浏览不方便的,有了PD ... -
D语言真相 The Case for D(1-5)
2009-06-17 09:52 4774D语言真相 Andrei Alexandre ... -
The Case for D
2009-06-16 22:50 2278The Case for D Andrei Alexan ... -
Python嵌入D
2009-06-12 11:37 1877所有的嵌入都研究了一个遍。发现嵌入Python挺好,试试。 ... -
实用的DFL注册表
2009-05-27 09:09 954应用中要用到注册表.DFL里面有. 参照了文档,写了一 ... -
DFL 2.027,1.041,2,3编译
2009-04-07 17:59 1555注:DFL已经更新,http://www.dprogrammi ... -
D2.0的字符串
2009-04-07 08:28 1348D2.0的字符串增加了常量,不变量和变量.在很大程度上增加了语 ... -
D语言编译器DMD开源了!
2009-03-05 19:56 3413自从1999年12月,Walter设计开发D语言以来,D语 ... -
D语言现状From2007
2009-03-02 15:32 1007I'm sure this was brought up in ... -
D语言GUI库简单比较
2009-02-20 15:25 3176通过对一些D语言可以使用的GUI进行比较,对初学者有个借 ... -
D语言脚本引擎简单比较
2009-02-19 14:38 1780经过长期的测试,使用,扩展代码编写,比较了D中可以使用的几种脚 ... -
D语言编译器开始支持Mac OSX
2009-02-15 18:25 1092D语言编译器开始支持Mac OSX。 D语言历经10年的发 ... -
触发DFL中的ComboBox控件的键盘事件
2009-02-06 12:04 1151class ComboxKeyDownFilter:IMess ... -
DFL分析(四)伟大的结构
2008-12-25 00:08 1391每个程序都有很多的代码编织而成.为了获得最大的兼容性,你要从容 ...
相关推荐
IOCP完成端口.rar
实现IOCP完成端口例子(服务器端和客户端)
IOCP完成端口源码,用于演示IOCP完成端口,VC++编制
IOCP完成端口模型 IOCP完成端口模型 IOCP完成端口模型
IOCP完成端口典型实现范例,有服务端和客户端,是一个考试系统。
一个iocp C++完成端口例子,简单实用,适用于初学者。
IOCP完成端口原理IOCP完成端口原理
4. 创建IO完成端口,将socket绑定到IO完成端口上 5. 根据当前机器CPU个数创建工作者线程池 6. 使用AcceptEx()提前创建客户socket,创建个数与CPU个数相关 以上准备工作全部完成 7. 工作者线程池 ...
UDP+IOCP完成端口实现多播.zip
windows socket网络编程之iocp完成端口模型的例子
C++语言实现的线程池,结合windowsIOCP完成端口,实现socket高并发服务端程序.zip
iocp完成端口框架实现
易语言IOCP完成端口源码,IOCP完成端口,Mem_Read_int,Mem_Write_int,子程序指针到整数,Call,GetAcceptExSockAddrs,AcceptEx,IntSocket,Socket_TCP,Socket_Bind,Socket_Listen,OverlappedCreate,OverlappedDestroy,...
用C++实现的,能高并发(可自己设定)和高连接数(20000以上)的TCP与UDP两种协议IOCP封装源码。有效解决了掉线、死机、超时的基本问题。
socket UDP多播+用IOCP完成端口的例子源码.zip
visual c++ socket IOCP完成端口实现网络数据传输 iocp服务器+客户端.zip Server端用的是同步的Accept函数
c# iocp完成端口 高并发服务器 + log4net日志 + SEH异常捕获 本人已搭建好 你们拿走就直接能用了。。
C++建高性能服务器,用完成端口模型是最高效的,而完成端口比较难理解,因此对它进行封装对初学者来说是个福音,本源码基于此背景,对IOCP进行封装,利于大家直接调用--本人发源码的原则是:不经典不发!
学习完成端口编程很好的资料。IOCP完成端口编程
1、在C#中,不用去面对完成端口的操作系统内核对象,Microsoft已经为我们提供了SocketAsyncEventArgs类,它封装了IOCP的使用。请参考:...