Server端:
var
  Form1: TForm1;
  iHandle: THandle;
  GlobalLock: TCriticalSection;
    
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
  iHandle:= CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
end;procedure TForm1.Button2Click(Sender: TObject);
var
  Addr: TSockAddr;
begin
  iSender:= WSASocket(AF_INET, SOCK_DGRAM, 0, nil, 0, WSA_FLAG_OVERLAPPED);
  Addr.sin_family:= AF_INET;
  Addr.sin_port:= htons(4545);
  Addr.sin_addr.S_addr:= inet_addr('127.0.0.1');
  if Bind(iSender, @Addr, Sizeof(Addr)) <> 0 then
  begin
    ShowMessage('绑定出错');
  end;
  if iSender <> INVALID_SOCKET then
  begin
    if CreateIoCompletionPort(iSender, iHandle, 0, 0) <> 0 then
    begin
      tWorkThread.Create;
    end;
  end;
end;{ tWorkThread }constructor tWorkThread.Create;
begin
  inherited Create(True);
  FreeOnTerminate := true;
  Resume;
end;procedure tWorkThread.Execute;
var
  HandleData: PPerHandleData;
  byteRece, Key: DWORD;
  OperPosted: boolean;
  errCode: integer;
begin
  while not Terminated do
  begin
    if not GetQueuedCompletionStatus(iHandle, byteRece, Key, POverlapped(HandleData), INFINITE) then
    begin
      errCode:= GetLastError;
      if errCode = 6 then
        Terminate;
      Continue;
    end
    else
      begin
        GlobalLock.Enter;
        case HandleData.Statu of
        ssRecv:
          begin
            ShowMessage('Recv');
          end;
        ssSend:
          begin
            ShowMessage('Send');
          end;
        end;
        GlobalLock.Leave;
      end;      end;
end;procedure TForm1.FormCreate(Sender: TObject);
var
  wsaData: TWSAData;
begin
  WSAStartup(makeword(2, 0), wsaData);
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
  WSACleanup;
end;initialization
  GlobalLock := TCriticalSection.Create;
finalization
  GlobalLock.Free;end.Client端:
procedure TForm1.FormCreate(Sender: TObject);
var
  wsaData: TWSAData;
begin
  WSAStartup(makeword(2, 0), wsaData);
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
  WSAcleanup;
end;procedure TForm1.Button1Click(Sender: TObject);
var
  addrin: TSockAddr;
  tmpPacket: array [0..8191] of byte;
begin
  iSender:= Socket(AF_INET, SOCK_DGRAM, 0);
  addrin.sin_family:= AF_INET;
  addrin.sin_port:= htons(4540);
  addrin.sin_addr.S_addr:= inet_addr('127.0.0.1');
  if Bind(iSender, @addrin, sizeof(addrin)) <> 0 then
    ShowMessage('绑定出错')
  else
    begin
      Sendto(iSender, tmpPacket, 8192, 0, addrin, sizeof(addrin));
    end;
end;

解决方案 »

  1.   

    给你改了一下:
    const
      BUFFER_SIZE = 4096;type
      YServerAction = ( saSend, saRecv, saClose, saSendAndClose, saBroadcast );
      //
      //扩展的WSAOVERLAPPED,即"Overlapped"(单句柄数据)
      //
      YPerOverlappedEx = record
        Overlap  : WSAOVERLAPPED;
        DataInf  : WSABUF;
        Buf      : Array [0..BUFFER_SIZE-1] of Char;
        Action   : YServerAction;
      end;
      PPerOverlappedEx = ^YPerOverlappedEx;  YWorkThread = class(TThread)
      private
        FCompletPort  : THandle;
      protected
        procedure Execute; override;
      end;var
      Form1: TForm1;
      iocp : THandle;
      sock : TSocket;
      workthread  : YWorkThread;implementation{$R *.dfm}
    procedure YWorkThread.Execute;
    var
      dwTransferd : DWORD;
      pOverlapEx  : PPerOverlappedEx;
      sock        : TSocket;
      dwTransfer, dwFlag : DWORD;
    begin
      while (not Terminated) do
      begin
        dwTransferd := 0;
        GetQueuedCompletionStatus( FCompletPort, dwTransferd, DWORD(sock),
            POVERLAPPED(pOverlapEx), 1000 );    if ( dwTransferd = 0 ) then
        begin
          if ( Sock = 0 ) or ( pOverlapEx = nil ) then
               continue;
        end;    case pOverlapEx^.Action of
          saRecv : //完成了接收数据任务(pOverlapEx内有接收到的数据)
          begin
            messagebox(0,'recved','iocp',mb_ok);        fillChar( pOverlapEx^.Overlap, sizeof(WSAOVERLAPPED), 0 );
            FillChar( pOverlapEx^.Buf[0], BUFFER_SIZE, 0 );
            pOverlapEx^.DataInf.len := BUFFER_SIZE;
            pOverlapEx^.DataInf.buf := pOverlapEx^.Buf;
            pOverlapEx^.Action := saRecv;
            dwFlag := 0;
            WSARecv( sock, @(pOverlapEx^.DataInf), 1, dwTransfer, dwFlag,
               @(pOverlapEx^.Overlap), nil );
          end;      saSend : ;//完成了发送数据任务
        end; //case pOverlapEx^.Action of
      end; //while not terminated
    end;procedure TForm1.FormCreate(Sender: TObject);
    var
      wsa : TWSAData;
    begin
      WSAStartup( $0202, wsa );
      ListBox1.Font.Name := 'Courier New';
      ListBox1.Font.Size := 9;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      WSACleanup;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      Addr: TSockAddr;
      pOverlapEx : PPerOverlappedEx;
      dwTransfer, dwFlag : DWORD;
    begin
      //先创建完成端口
      iocp := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);  //再创建线程
      WorkThread := YWorkThread.Create( true );
      WorkThread.FCompletPort := iocp;
      WorkThread.FreeOnTerminate := true;
      WorkThread.Resume;  //再创建socket
      sock := Socket( AF_INET, SOCK_DGRAM, 0  );
      Addr.sin_family:= AF_INET;
      Addr.sin_port:= htons(4545);
      Addr.sin_addr.S_addr:= inet_addr('192.168.1.12');  if Bind( sock, @Addr, Sizeof(Addr) ) <> 0 then
      begin
        ShowMessage('绑定出错');
        closehandle( iocp );
        Exit;
      end;  //然后把socket和iocp绑定
      CreateIoCompletionPort( sock, iocp, sock, 0 );  //最后,要投递一个recv请求
      New( pOverlapEx );
      fillChar( pOverlapEx^.Overlap, sizeof(WSAOVERLAPPED), 0 );
      FillChar( pOverlapEx^.Buf[0], BUFFER_SIZE, 0 );
      pOverlapEx^.DataInf.len := BUFFER_SIZE;
      pOverlapEx^.DataInf.buf := pOverlapEx^.Buf;
      pOverlapEx^.Action := saRecv;  dwFlag := 0;
      WSARecv( sock, @(pOverlapEx^.DataInf), 1, dwTransfer, dwFlag,
               @(pOverlapEx^.Overlap), nil );
    end;end.
      

  2.   

    呵呵,把两个地方的WSARecv改为WSARecvfrom罢 
    len := sizeof(addr);
      fillchar(addr,len,0);
      WSARecvfrom( sock, @(pOverlapEx^.DataInf), 1, dwTransfer, dwFlag,
          @addr,@len,     @(pOverlapEx^.Overlap), nil );