亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Delphi > 正文

Winsock完成端口模型-Delphi代碼

2019-11-18 18:03:40
字體:
來源:轉載
供稿:網友
 

原文出處 《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 ;
begin
   CompletionPort := THANDLE( CompletionPortID);

   Result:= 0;

   while(TRUE) do
   begin

      if (GetQueuedCompletionStatus(CompletionPort, BytesTransferred,
         DWORD(PerHandleData), POverlapped(PerIoData), INFINITE) = False) then
      begin
         printf('GetQueuedCompletionStatus 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
      // associated with the socket.

      if (BytesTransferred = 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 means a WSARecv call just completed so update the BytesRECV field
      // with the BytesTransferred value from the completed WSARecv() call.

      if (PerIoData.BytesRECV = 0) then
      begin
         PerIoData.BytesRECV := BytesTransferred;
         PerIoData.BytesSEND := 0;
      end
      else
      begin
         PerIoData.BytesSEND := PerIoData.BytesSEND + BytesTransferred;
      end;

      if (PerIoData.BytesRECV > PerIoData.BytesSEND) 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.Overlapped), sizeof(OVERLAPPED));

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

         if (WSASend(PerHandleData.Socket, @(PerIoData.DataBuf), 1, @SendBytes, 0,
            @(PerIoData.Overlapped), nil) = SOCKET_ERROR) then
         begin
            if (WSAGetLastError() <> 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.Overlapped), sizeof(OVERLAPPED));

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

         if (WSARecv(PerHandleData.Socket, @(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;
end;


end.


上一篇:在Delphi里播放Flash

下一篇:Delphi中的布爾類型

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美一乱一性一交一视频| 国产精品爱久久久久久久| 92国产精品视频| 国内精品小视频| 国产欧美一区二区三区在线看| 日韩av免费在线观看| 久久久成人的性感天堂| 日韩亚洲一区二区| 亚洲男人天堂2024| 欧美黑人巨大xxx极品| 综合国产在线观看| 丰满岳妇乱一区二区三区| 尤物99国产成人精品视频| 亚洲精品国精品久久99热一| 在线观看日韩欧美| 亚洲天堂男人天堂女人天堂| 欧美视频在线观看 亚洲欧| 久久久视频在线| 国产成人a亚洲精品| 欧美日韩国产中字| 最新亚洲国产精品| 国产噜噜噜噜噜久久久久久久久| 中文字幕在线国产精品| 亚洲精品国偷自产在线99热| 久久人人爽亚洲精品天堂| 久久影院资源网| 亚洲国产高潮在线观看| 欧美日本亚洲视频| 日本三级久久久| 久久精视频免费在线久久完整在线看| 国产精品久久久久久久久久小说| 亚洲国产免费av| 亚洲精品一二区| 57pao国产精品一区| 91精品视频大全| 亚洲电影免费观看高清完整版在线| 欧美大胆在线视频| 日韩欧美高清在线视频| 国产精品久久久久久网站| 国产精品第一第二| 精品国产31久久久久久| 热久久99这里有精品| 日韩av在线免费观看| 欧美激情网站在线观看| 日韩最新中文字幕电影免费看| 欧美精品久久久久| 精品久久香蕉国产线看观看gif| 亚洲女人天堂av| 国产精品久久久av久久久| 欧美性猛交xxxx乱大交极品| 亚洲黄色av女优在线观看| 中文字幕在线看视频国产欧美在线看完整| 日本亚洲欧洲色α| 欧美激情精品久久久久久大尺度| 在线亚洲欧美视频| 日韩视频在线免费观看| 成人综合网网址| 国产精品久久久av久久久| 日韩视频一区在线| 91精品久久久久久久久久久| 国产精品久久久久7777婷婷| 在线观看国产精品淫| 伊人久久久久久久久久久久久| 国内精品久久久久| 久久精品一本久久99精品| 国产日韩精品视频| 久久成人综合视频| 在线国产精品视频| 亚洲视频专区在线| 国产区精品视频| 国产成人短视频| 国产在线播放不卡| 中文字幕日韩免费视频| 91夜夜未满十八勿入爽爽影院| 97国产精品视频人人做人人爱| 日本久久精品视频| 韩国三级日本三级少妇99| 国产日韩欧美黄色| 国产九九精品视频| www.欧美三级电影.com| 久久久久久久电影一区| 欧美日韩视频免费播放| 国产精品视频yy9099| 中国人与牲禽动交精品| 欧美精品在线第一页| 色妞色视频一区二区三区四区| 日韩在线资源网| 亚洲精品在线视频| 亚洲国产精品成人一区二区| 成人福利视频网| 成人综合国产精品| 久久久久久亚洲精品| 久久中文久久字幕| 亚洲国产精品yw在线观看| 国产suv精品一区二区| 国产亚洲人成网站在线观看| 精品免费在线观看| 欧美美女18p| 91在线色戒在线| 亚洲字幕在线观看| 黄色91在线观看| 欧美极品少妇xxxxⅹ免费视频| 亚洲图片制服诱惑| 欧美激情免费看| www.色综合| 亚洲免费精彩视频| 韩国福利视频一区| 亚洲精品视频二区| 欧美一级高清免费播放| 中文字幕欧美亚洲| 亚洲综合在线做性| 亚洲韩国青草视频| 欧美裸体男粗大视频在线观看| 国产97人人超碰caoprom| 98精品国产高清在线xxxx天堂| 亚洲国产精品成人精品| 在线电影av不卡网址| 精品国产91乱高清在线观看| 欧美在线一级va免费观看| 97超碰国产精品女人人人爽| 亚洲美女视频网站| 在线观看欧美www| 欧美成人一区二区三区电影| 日本欧美黄网站| 亚洲片av在线| 欧美野外wwwxxx| 自拍偷拍亚洲精品| 欧美激情久久久久| 欧美亚洲一区在线| 亚洲第一精品自拍| 尤物yw午夜国产精品视频明星| 欧美亚洲国产精品| 日本精品一区二区三区在线| 91精品国产沙发| 日韩高清中文字幕| 欧美做受高潮1| 亚洲欧美国产高清va在线播| 久久国产精品视频| 欧美一性一乱一交一视频| 深夜福利国产精品| 亚洲女人天堂av| 国产精品视频成人| 国产经典一区二区| 国产日韩欧美在线看| 亚洲国产精品热久久| 1769国内精品视频在线播放| 欧美日韩国产二区| 欧美中文字幕在线| 国产亚洲精品日韩| 国产亚洲成av人片在线观看桃| 国产精品免费看久久久香蕉| 国产日韩欧美在线视频观看| 欧美日韩激情视频| 日韩精品高清在线观看| 91爱爱小视频k| 久久夜色精品亚洲噜噜国产mv| 91av在线国产| 国产精品99久久久久久久久| 国产成人精品电影| 亚洲欧美日韩第一区| 国产精品男人的天堂| 国产精品成熟老女人| 久久九九亚洲综合| 日本精品中文字幕|