DELPHI中完成端口(IOCP)的简单分析(1)

简介:
(希望大家在转贴的时候注明出处,谢谢)
用DELPHI开发网络代码已经有一段时间了!
我发现在网上用VC来实现完成端口(IOCP)的代码很多,但是使用DELPHI来实现的就比较少了。对IOCP讲的清楚的就更少了。在这里我把自己编写DELPHI下的IOCP写出来,希望对刚学完成端口的朋友有个帮助。
首先我们来了解一些在使用IOCP的时候需要使用的一些结构!
(1):单IO数据结构
  LPVOID = Pointer;
  LPPER_IO_OPERATION_DATA = ^ PER_IO_OPERATION_DATA ;
  PER_IO_OPERATION_DATA = packed record
    Overlapped: OVERLAPPED;
    DataBuf: TWSABUF;
    Buffer: array [0..1024] of CHAR;
    BytesSEND: DWORD;
    BytesRECV: DWORD;
  end;
上面的结构中Overlapped: OVERLAPPED;和DataBuf: TWSABUF;是固定的结构类型。Buffer: array [0..1024] of CHAR;是用来保存接受数据的缓存。BytesSEND: DWORD;用来标志发送数据的长度。BytesRECV: DWORD;用来标志接受数据的长度。因为完成端口的工作者线程可以接受到来自客户端的数据,同时还可以接受到自己发送给客户端的数据,所以我们使用BytesSEND,BytesRECV变量来说是用来区分这次的数据是来自客户端的数据还是自己发送出去的数据。详细的使用方法,我会在下面详细说明。
(2):“单句柄数据结构”
  LPPER_HANDLE_DATA = ^ PER_HANDLE_DATA;
  PER_HANDLE_DATA = packed record
    Socket: TSocket;
  end;
下来我从编写一个完成端口的为例说明。
if WSAStartUp($202, wsData) <> 0 then
begin
   WSACleanup();
end;
加载SOCKET。我使用的是2.2版为了后面方便加入心跳。
CompletionPort:=CreateIOCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
创建一个完成端口。
GetSystemInfo(LocalSI);
for I:=0 to LocalSI.dwNumberOfProcessors * 2 -1 do
begin
   hThread := CreateThread(nil, 0, @ServerWorkerThread, Pointer(CompletionPort),0, ThreadID);
   if (hThread = 0) then
   begin
       Exit;
   end;
   CloseHandle(hThread);
end;
根据CPU的数量创建CPU*2数量的工作者线程。
Listensc:=WSASocket(AF_INET,SOCK_STREAM,0,Nil,0,WSA_FLAG_OVERLAPPED);
if Listensc=SOCKET_ERROR then
begin
    closesocket(Listensc);
    WSACleanup();
end;
sto.sin_family:=AF_INET;
sto.sin_port:=htons(5500);
sto.sin_addr.s_addr:=htonl(INADDR_ANY);
if bind(Listensc,sto,sizeof(sto))=SOCKET_ERROR then
begin
   closesocket(Listensc);
end;
listen(Listensc,20);
创建一个套接字,将此套接字和一个端口绑定并监听此端口。
while (TRUE) do
begin
   Acceptsc:= WSAAccept(Listensc, nil, nil, nil, 0);
   当客户端有连接请求的时候,WSAAccept函数会新创建一个套接字Acceptsc。这个套接字就是和客户端通信的时候使用的套接字。
   if (Acceptsc= SOCKET_ERROR) then
   begin
      closesocket(Listensc);
      exit;
   end;
   判断Acceptsc套接字创建是否成功,如果不成功则退出。
   PerHandleData := LPPER_HANDLE_DATA (GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA)));
   if (PerHandleData = nil) then
   begin
      exit;
   end;
   PerHandleData.Socket := Acceptsc;
   创建一个“单句柄数据结构”将Acceptsc套接字绑定。
   if (CreateIoCompletionPort(Acceptsc, CompletionPort, DWORD(PerHandleData), 0) = 0) then
   begin
      exit;
   end;
   将套接字、完成端口和“单句柄数据结构”三者绑定在一起。
   PerIoData := LPPER_IO_OPERATION_DATA(GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA)));
   if (PerIoData = nil) then
   begin
      exit;
   end;
   ZeroMemory(@PerIoData.Overlapped, sizeof(OVERLAPPED));
   PerIoData.BytesSEND := 0;
   PerIoData.BytesRECV := 0;
   PerIoData.DataBuf.len := 1024;
   PerIoData.DataBuf.buf := @PerIoData.Buffer;
   Flags := 0;
   创建一个“单IO数据结构”其中将PerIoData.BytesSEND 和PerIoData.BytesRECV 均设置成0。说明此“单IO数据结构”是用来接受的。
   if (WSARecv(Acceptsc, @(PerIoData.DataBuf), 1, @RecvBytes, @Flags,@(PerIoData.Overlapped), nil) = SOCKET_ERROR) then
   begin
      if (WSAGetLastError() <> ERROR_IO_PENDING) then
      begin
         //最近在检查代码的时候发现以前这里只是使用Exit来退出是不正确的。这里需要删除申请的单IO数据结构,否子会出现内存泄露。 (2008年3月24日)
         //Exit;
        closesocket(AcceptSc);
        if PerIoData <> nil then
        begin
          GlobalFree(DWORD(PerIoData));
        end;
        Continue;
      end
   end;
   用此“单IO数据结构”来接受Acceptsc套接字的数据。
end;
创建IOCP的工作已经完成,下一次我将写IOCP的工作者线程的处理方法,谢谢!
本文转自狗窝博客51CTO博客,原文链接http://blog.51cto.com/fxh7622/7667如需转载请自行联系原作者

fxh7622
相关文章
端口排查步骤-7680端口分析-Dosvc服务
对通过服务启动的进程查找主进程
6527 0
|
网络协议 开发工具 Android开发
【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )
【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )
372 0
【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )
|
消息中间件 API Windows
[转载]理解 I/O Completion Port (IOCP完成端口)
原文:理解 I/O Completion Port (IOCP完成端口)欢迎阅读此篇IOCP教程。我将先给出IOCP的定义然后给出它的实现方法,最后剖析一个Echo程序来为您拨开IOCP的谜云,除去你心中对IOCP的烦恼。
1090 0
|
消息中间件 Windows 负载均衡
|
Web App开发 Ubuntu 测试技术
ubuntu16.04-x64系统中Jexus web server部署.NetCore和端口分析引发的猜想!
您有这样的牢骚么? 有一周没更新博客了,简单说下在干什么吧;主要是公司安排对接某旅游大公司的接口,接口数量倒也就10个左右,对接完后还需要加入到业务系统中和App端,因此还是需要花点时间的;时间上来说业务需求安排在6月最后一周上线,整个3周的时间,就本人一人负责,由于在这之前对接过另外一个公司接口,我已经搭建好了整体架构和提供给app端接口了,因此主要还是对接某公司接口而已,至于细节上的东西改改后台系统,调调数据格式应该就差不多了;就本人开发的熟练度来讲一周时间基本能搞定,其他剩余时间就测试,喝喝茶,学习一下;谁知。
1230 0
完成端口(IOCP) 也可以这样用~~呵呵~ 用来充当线程之间的数据队列~
// Test32.cpp : 定义控制台应用程序的入口点。//#include "stdafx.
827 0

热门文章

最新文章