设为首页】 【加入收藏】 【网站地图】 【商品折扣
娱乐一生 娱乐明星
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
首页  |  java  |  .NET  |  C/C++  |  网页技术  |  php  |  asp  |  delphi  |  VC  |  VB开发  |  游戏开发  |  软件工程  |  Power Builder  |  Linux开发  |  Windows开发技巧
当前位置:首页 >> delphi >> Winsock完成端口模型-Delphi代码_Delphi教程_src119.com

Winsock完成端口模型-Delphi代码_Delphi教程_src119.com -

 

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

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

 

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

 

 

program CompletionIO;

{$A TYPE CO OLE}

uses
  SysUtils,
  Wi ock2 in 'Wi ock2.pas',
  Mai  in 'Mai .pas';

begin
  main();
end.

 

 

// Module Name: iocmplt.c 
//
// Description:
//
//  This sample illustrates how to develop a simple echo server Wi ock
//  a lication using the completeion port I/O model. This
//  sample is implemented as a co ole-style a lication and simply prints
//  me ages when co ectio  are established and removed from the server.
//  The a lication liste  for TCP co ectio  on port 5150 and accepts them
//  as they arrive. When this a lication 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 co ection.
//
//  2005-2-5
//  c  convert to delphi pa  by joh on
// 

unit Mai 

interface

uses Windows, Wi ock2, Wi ock, Sysutil 

co t
 ORT  = 5150;
 DATA_BUFSIZE = 8192;


type
  LPVOID = Pointer;
  L ER_IO_OPERATION_DATA = ^ PER_IO_OPERATION_DATA ;
  PER_IO_OPERATION_DATA = packed record
  Overla ed: OVERLA ED;
  DataBuf: TWSABUF;
  Buffer: array [0..DATA_BUFSIZE] of CHAR;
  Byte END: DWORD;
  BytesRECV: DWORD;
  end;

  L ER_HANDLE_DATA = ^ PER_HANDLE_DATA;
  PER_HANDLE_DATA = packed record
  Socket: TSocket;
  end;

  procedure mai 

implementation

function ServerWorkerThread(Completio ortID: LPVOID): DWORD; stdcall; forward;

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

procedure mai 
var
  InternetAddr: SOCKADDR_I 
  Listen: TSOCKET;
  Accept: TSOCKET;
  Completio ort: THANDLE ;
  SystemInfo: SYSTEM_INFO ;
  PerHandleData: L ER_HANDLE_DATA ;
  PerIoData: L ER_IO_OPERATION_DATA ;
  i: Integer;
  RecvBytes:  DWORD;
  Flags: DWORD;
  ThreadID: DWORD ;
  wsaData: TWSADATA ;
  Ret: DWORD ;

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

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


  // Determine how many proce ors are on the system.

  GetSystemInfo(SystemInfo);

  // Create worker threads based on the number of proce ors available on the
  // system. Create two worker threads for each proce or.

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

  // Create a server worker thread and pa  the completion port to the thread.
  ThreadHandle := CreateThread(nil, 0, @ServerWorkerThread, Pointer(Completio ort),
  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_OVERLA ED);
  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 := hto (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 (Wi ock.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 co ectio  and a ign 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 a ociate with the socket
  PerHandleData := L ER_HANDLE_DATA (GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA)));
  if (PerHandleData = nil) then
  begin
  printf('GlobalAlloc() failed with error %d', WSAGetLastError());
  exit;
  end;

  // A ociate the accepted socket with the original completion port.

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

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

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

  PerIoData := L ER_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.Overla ed, sizeof(OVERLA ED));
  PerIoData.Byte END := 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.Overla ed), nil) = SOCKET_ERROR) then
  begin
  if (WSAGetLastError() < gt; ERROR_IO_PENDING) then
  begin
  printf('WSARecv() failed with error %d', WSAGetLastError());
  exit;
  end
  end;

  end;
end;


function ServerWorkerThread(Completio ortID: LPVOID): DWORD; stdcall;
var
  Completio ort: THANDLE;
  BytesTra ferred: DWORD ;
 //  Overla ed: POVERLA ED;
  PerHandleData: L ER_HANDLE_DATA ;
  PerIoData: L ER_IO_OPERATION_DATA ;
  SendBytes, RecvBytes: DWORD;
  Flags: DWORD ;
begin
  Completio ort := THANDLE( Completio ortID);

  Result:= 0;

  while(TRUE) do
  begin

  if (GetQueuedCompletio tatus(Completio ort, BytesTra ferred,
  DWORD(PerHandleData), POverla ed(PerIoData), INFINITE) = False) then
  begin
  printf('GetQueuedCompletio tatus failed with error %d', GetLastError());
  exit;
  end;

  // First check to see if an error has occured on the socket and if so
  // then close the socket and cleanup the SOCKET_INFORMATION structure
  // a ociated with the socket.

  if (BytesTra ferred = 0) then
  begin
  printf('Closing socket %d\', PerHandleData.Socket);

  if (closesocket(PerHandleData.Socket) = SOCKET_ERROR) then
  begin
  printf('closesocket() failed with error %d', WSAGetLastError());
  exit;
  end;

  GlobalFree(DWORD(PerHandleData));
  GlobalFree(DWORD(PerIoData));
  continue;
  end;

  // Check to see if the BytesRECV field equals zero. If this is so, then
  // this mea  a WSARecv call just completed so update the BytesRECV field
  // with the BytesTra ferred value from the completed WSARecv() call.

  if (PerIoData.BytesRECV = 0) then
  begin
  PerIoData.BytesRECV := BytesTra ferred;
  PerIoData.Byte END := 0;
  end
  else
  begin
  PerIoData.Byte END := PerIoData.Byte END + BytesTra ferred;
  end;

  if (PerIoData.BytesRECV > PerIoData.Byte END) then
  begin

  // Post another WSASend() request.
  // Since WSASend() is not gauranteed to send all of the bytes requested,
  // continue posting WSASend() calls until all received bytes are sent.

  ZeroMemory(@(PerIoData.Overla ed), sizeof(OVERLA ED));

  PerIoData.DataBuf.buf := PerIoData.Buffer + PerIoData.Byte END;
  PerIoData.DataBuf.len := PerIoData.BytesRECV - PerIoData.Byte END;

  if (WSASend(PerHandleData.Socket, @(PerIoData.DataBuf), 1, @SendBytes, 0,
  @(PerIoData.Overla ed), nil) = SOCKET_ERROR) then
  begin
  if (WSAGetLastError() < gt; ERROR_IO_PENDING) then
  begin
  printf('WSASend() failed with error %d', WSAGetLastError());
  Exit;
  end;
  end;
  end
  else
  begin
  PerIoData.BytesRECV := 0;

  // Now that there are no more bytes to send post another WSARecv() request.

  Flags := 0;
  ZeroMemory(@(PerIoData.Overla ed), sizeof(OVERLA ED));

  PerIoData.DataBuf.len := DATA_BUFSIZE;
  PerIoData.DataBuf.buf := @PerIoData.Buffer;

  if (WSARecv(PerHandleData.Socket, @(PerIoData.DataBuf), 1, @RecvBytes, @Flags,
  @(PerIoData.Overla ed), nil) = SOCKET_ERROR) then
  begin
  if (WSAGetLastError() < gt; ERROR_IO_PENDING) then
  begin
  printf('WSARecv() failed with error %d', WSAGetLastError());
  exit;
  end;
  end;
  end;
  end;
end;


end.



 

娱乐图摘

更多 >>

靓丽清纯美女meimei

美女私房全裸照
导演劝女演员脱衣服(视频)

大胆火辣人体艺术写真(图)

黑丝妹妹热辣诱惑-丝袜美女妹妹

PLMM 漂亮妹妹图集-妹妹图库

全球美女图库-美女集中营

52MM 我爱漂亮妹妹-制服妹妹诱惑

图王图库-世界美女明星图片资料库
美女写真集锦

激情两性-解密性生活
浴室MM湿身内衣诱惑
邻家小妹洗澡被偷拍(视频)

热点文章

更多

· 使用MIDAS访问远程Access数据库_Delphi教程_
· Delphi2005学习笔记4——再谈NameSpace和D
· 多层数据库开发十二:使用数据控件_Delphi教程_src1
· 在Delphi中自己建立交叉表_Delphi教程_src11
· 用Delphi设计代理服务器_Delphi教程_src119
· Delphi开发单机瘦数据库程序要点_Delphi教程_sr
· 拖拉打开文件_Delphi教程_src119.com
· 搜索字符串在流中的位置_Delphi教程_src119.co
· 用Delphi编写Win2000服务程序_Delphi教程_
· 創建一個簡單的"專家"_Delphi教程

热点文章

更多