- 浏览: 329496 次
-
最新评论
-
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 922最近抽空翻译了D语言实用入门教程 地址在Github,供初 ... -
编译WxD0.16
2011-09-27 18:09 1743wx我在Python环境下用了 ... -
简单看了下DGui
2011-09-26 10:39 2310很久没有写代码了。。。。 怀念往日不如今天行动。生疏了 ... -
支持中文录入的harmonia
2010-08-16 22:40 1053harmonia界面很方便,发现不能录入中文.Patch一下. ... -
控制台得到密码不回显
2009-09-18 22:37 1287看到坛子有人问“在D或C下如何实现输入单个字符不回显?可能的应 ... -
D资源文件调用
2009-08-09 01:36 1083终于成功了。 资源文件太可爱,竟然可以如此。按名称进行 ... -
The Case for D中英文版PDF下载
2009-06-19 10:27 1427The Case for D 在网站上浏览不方便的,有了PD ... -
D语言真相 The Case for D(1-5)
2009-06-17 09:52 4943D语言真相 Andrei Alexandre ... -
The Case for D
2009-06-16 22:50 2329The Case for D Andrei Alexan ... -
Python嵌入D
2009-06-12 11:37 2012所有的嵌入都研究了一个遍。发现嵌入Python挺好,试试。 ... -
实用的DFL注册表
2009-05-27 09:09 1046应用中要用到注册表.DFL里面有. 参照了文档,写了一 ... -
DFL 2.027,1.041,2,3编译
2009-04-07 17:59 1620注:DFL已经更新,http://www.dprogrammi ... -
D2.0的字符串
2009-04-07 08:28 1398D2.0的字符串增加了常量,不变量和变量.在很大程度上增加了语 ... -
D语言编译器DMD开源了!
2009-03-05 19:56 3531自从1999年12月,Walter设计开发D语言以来,D语 ... -
D语言现状From2007
2009-03-02 15:32 1084I'm sure this was brought up in ... -
D语言GUI库简单比较
2009-02-20 15:25 3295通过对一些D语言可以使用的GUI进行比较,对初学者有个借 ... -
D语言脚本引擎简单比较
2009-02-19 14:38 1847经过长期的测试,使用,扩展代码编写,比较了D中可以使用的几种脚 ... -
D语言编译器开始支持Mac OSX
2009-02-15 18:25 1190D语言编译器开始支持Mac OSX。 D语言历经10年的发 ... -
触发DFL中的ComboBox控件的键盘事件
2009-02-06 12:04 1218class ComboxKeyDownFilter:IMess ... -
DFL分析(四)伟大的结构
2008-12-25 00:08 1437每个程序都有很多的代码编织而成.为了获得最大的兼容性,你要从容 ...
相关推荐
IOCP 完成端口编程 《远程控制编程技术》源代码 内含(重启、图片操作、ip操作、键盘与鼠标、客户端以及服务端、文件传输等实例源码) 多个VC++加密解密算法库(CRYPT++) 详细讲解了Crypt++的加密解密的使用以及...
IOCP 完成端口编程技术 《远程控制编程技术》源代码 内含(重启、图片操作、ip操作、键盘与鼠标、客户端以及服务端、文件传输等实例源码) 多个VC++加密解密算法库(CRYPT++) 详细讲解了Crypt++的加密解密的使用...
IOCP 完成端口编程 《远程控制编程技术》源代码 内含(重启、图片操作、ip操作、键盘与鼠标、客户端以及服务端、文件传输等实例源码) 多个VC++加密解密算法库(CRYPT++) 详细讲解了Crypt++的加密解密的使用以及...
IOCP完成端口 IP所在地查询器 jpeglib_demo 处理Jpeg图片。 KeyHook 键盘钩子,截获键盘信息。 Kugou7+UI 界面设计。学习界面的好实例,强烈推荐。 自绘button 自绘MENU 自绘tab 自绘Tree 自绘按钮button源代码...
IOCP完成端口 IP所在地查询器 jpeglib_demo 处理Jpeg图片。 KeyHook 键盘钩子,截获键盘信息。 Kugou7+UI 界面设计。学习界面的好实例,强烈推荐。 自绘button 自绘MENU 自绘tab 自绘Tree 自绘按钮button源代码...
举个最简单的例子,有时在授权、防破解等应用中,我们需要获取准确的北京时间。一般我们为了方便会通过第三方来获取:找个提供北京时间的第三方web页面;写个模块或DLL,提取页面里的北京时间;弊端:如果第三方页面...