转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
Winsock完成端口模型-Delphi代码         ★★★★

Winsock完成端口模型-Delphi代码

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1402 更新时间:2009/4/23 18:27:12

原文出处 《Windows网络编程技术》第8章 完成端口模型

由于原书附的是C代码,我把其翻译成Delphi代码。

 

其中winsock2.pas在delphi中不带,要另外下载http://jungla.dit.upm.es/~bti/files/winsock2.pas

 

 

program CompletionIO;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  WinSock2 in ''''WinSock2.pas'''',
  Mains in ''''Mains.pas'''';

begin
    main();
end.

 

 

// Module Name: iocmplt.cpp
//
// Description:
//
//    This sample illustrates how to develop a simple echo server Winsock
//    application using the completeion port I/O model. This
//    sample is implemented as a console-style application and simply prints
//    messages when connections are established and removed from the server.
//    The application listens for TCP connections on port 5150 and accepts them
//    as they arrive. When this application receives data from a client, it
//    simply echos (this is why we call it an echo server) the data back in
//    it''''s original form until the client closes the connection.
//
//  2005-2-5
//    cpp convert to delphi pas  by johnson
//   

unit Mains;

interface

uses Windows, WinSock2, WinSock, Sysutils;

const
 PORT         = 5150;
 DATA_BUFSIZE = 8192;


type
  LPVOID = Pointer;
  LPPER_IO_OPERATION_DATA = ^ PER_IO_OPERATION_DATA ;
  PER_IO_OPERATION_DATA = packed record
    Overlapped: OVERLAPPED;
    DataBuf: TWSABUF;
    Buffer: array [0..DATA_BUFSIZE] of CHAR;
    BytesSEND: DWORD;
    BytesRECV: DWORD;
  end;

  LPPER_HANDLE_DATA = ^ PER_HANDLE_DATA;
  PER_HANDLE_DATA = packed record
    Socket: TSocket;
  end;

  procedure main;

implementation

function ServerWorkerThread(CompletionPortID: LPVOID): DWORD; stdcall; forward;

procedure printf(Fmt: string; num: Integer);
begin
  WriteLn(Format(Fmt, [num]));
end;

procedure main;
var
  InternetAddr: SOCKADDR_IN;
  Listen: TSOCKET;
  Accept: TSOCKET;
  CompletionPort: THANDLE ;
  SystemInfo: SYSTEM_INFO ;
  PerHandleData: LPPER_HANDLE_DATA ;
  PerIoData: LPPER_IO_OPERATION_DATA ;
  i: Integer;
  RecvBytes:  DWORD;
  Flags: DWORD;
  ThreadID: DWORD ;
  wsaData: TWSADATA ;
  Ret: DWORD ;

  ThreadHandle: THANDLE;
begin
    Ret := WSAStartup($0202, wsaData);
    if (Ret <> 0) then
    begin
      printf(''''WSAStartup failed with error %d'''', Ret);
      Exit;
    end;

   // Setup an I/O completion port.
   CompletionPort := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
   if (CompletionPort = 0) then
   begin
      printf( ''''CreateIoCompletionPort failed with error: %d'''', GetLastError());
      Exit;
   end;


   // Determine how many processors are on the system.

   GetSystemInfo(SystemInfo);

   // Create worker threads based on the number of processors available on the
   // system. Create two worker threads for each processor.

   for i:= 0 to SystemInfo.dwNumberOfProcessors * 2 - 1 do
   begin

      // Create a server worker thread and pass the completion port to the thread.
      ThreadHandle := CreateThread(nil, 0, @ServerWorkerThread, Pointer(CompletionPort),
         0, ThreadID);
      if (ThreadHandle = 0) then
      begin
         printf(''''CreateThread() failed with error %d'''', GetLastError());
         Exit;
      end;

      // Close the thread handle
      CloseHandle(ThreadHandle);
   end;

   // Create a listening socket
   Listen := WSASocket(AF_INET, SOCK_STREAM, 0, nil, 0, WSA_FLAG_OVERLAPPED);
   if (Listen = INVALID_SOCKET) then
   begin
      printf(''''WSASocket() failed with error %d'''', WSAGetLastError());
      exit;
   end;

   InternetAddr.sin_family := AF_INET;
   InternetAddr.sin_addr.s_addr := htonl(INADDR_ANY);
   InternetAddr.sin_port := htons(PORT);

   if (bind(Listen, InternetAddr, sizeof(InternetAddr)) = SOCKET_ERROR) then
   begin
      printf(''''bind() failed with error %d'''', WSAGetLastError());
      exit;
   end;

   // Prepare socket for listening

 

   if (Winsock.listen(Listen, 5) = SOCKET_ERROR) then
   begin
      printf(''''listen() failed with error %d'''', WSAGetLastError());
      exit;
   end
   else
   begin
      printf(''''Server listen on port = %d ...'''', PORT);
   end;


   // Accept connections and assign to the completion port.
   while(TRUE) do
   begin
      Accept := WSAAccept(Listen, nil, nil, nil, 0);
      if (Accept = SOCKET_ERROR) then
     begin
        printf(''''WSAAccept() failed with error %d'''', WSAGetLastError());
        exit;
     end;

      // Create a socket information structure to associate with the socket
      PerHandleData := LPPER_HANDLE_DATA (GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA)));
      if (PerHandleData = nil) then
      begin
        printf(''''GlobalAlloc() failed with error %d'''', WSAGetLastError());
        exit;
      end;

      // Associate the accepted socket with the original completion port.

      printf(''''Socket number %d connected'''', Accept);
      PerHandleData.Socket := Accept;

      if (CreateIoCompletionPort(Accept, CompletionPort, DWORD(PerHandleData), 0) = 0) then
      begin
        printf(''''CreateIoCompletionPort() failed with error %d'''', WSAGetLastError());
        exit;
      end;

      // Create per I/O socket information structure to associate with the
      // WSARecv call below.

      PerIoData := LPPER_IO_OPERATION_DATA(GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA)));
      if (PerIoData = nil) then
      begin
        printf(''''GlobalAlloc() failed with error %d'''', WSAGetLastError());
        exit;
      end;

      ZeroMemory( @PerIoData.Overlapped, sizeof(OVERLAPPED));
      PerIoData.BytesSEND := 0;
      PerIoData.BytesRECV := 0;
      PerIoData.DataBuf.len := DATA_BUFSIZE;
      PerIoData.DataBuf.buf := @PerIoData.Buffer;

      Flags := 0;
      if (WSARecv(Accept, @(PerIoData.DataBuf), 1, @RecvBytes, @Flags,
         @(PerIoData.Overlapped), nil) = SOCKET_ERROR) then
      begin
         if (WSAGetLastError() <> ERROR_IO_PENDING) then
         begin
           printf(''''WSARecv() failed with error %d'''', WSAGetLastError());
           exit;
         end
      end;

    end;
end;


function ServerWorkerThread(CompletionPortID: LPVOID): DWORD; stdcall;
var
   CompletionPort: THANDLE;
   BytesTransferred: DWORD ;
 //  Overlapped: POVERLAPPED;
   PerHandleData: LPPER_HANDLE_DATA ;
   PerIoData: LPPER_IO_OPERATION_DATA ;
   SendBytes, RecvBytes: DWORD;
   Flags: DWORD

[1] [2]  下一页


[系统软件]InstallShield Express for delphi制作安装程序定…  [常用软件]InstallShield Express制作Delphi数据库安装程序
[Delphi程序]为什么选择Delphi.Net ?  [Delphi程序]《关于VisiBroker For Delphi的使用》(4)
[Delphi程序]Delphi 程序员代码编写标准指南  [Delphi程序]转贴:Conversion to Delphi 6: Missing unit Pro…
[Delphi程序]Borland Delphi 9 的新特性  [Delphi程序]Delphi 键盘码表
[Delphi程序]Chuck Jazdzewski的离开意味着Delphi的终结吗?  [Delphi程序]Delphi Access violations 问题的解决之道
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台