WinSock学习笔记4:WSAEventSelect模型

WinSock学习笔记4:WSAEventSelect模型

WSAEventSelect类似于WSAAsycnSelect,区别就是当Socket上有“事件”时,传递一个Event而不是Windows消息。

 

unit Unit1;

interface

uses
  WinSock2, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TWorkThread 
=   class (TThread)
  
private
    FMemo: TMemo;
    FBuff: array [
0 .. 10 ] of Char;
    procedure ShowRecv;
  
protected
    procedure Execute;
override ;
  
public
    constructor Create(Memo: TMemo);
  end;

  TForm1 
=   class (TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  
private
    { Private declarations }
  
public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R 
* .dfm}

{ TWorkThread }

constructor TWorkThread.Create(Memo: TMemo);
begin
  inherited Create(False);

  FMemo:
=  Memo;
end;

procedure TWorkThread.Execute;
var
  WSData: TWSAData;
  LocalAddr: TSockAddrIn;
  ClientAddr: TSockAddrIn;
  ClientAddrLen: Integer;
  ServerSocket: TSocket;
  ClientSocket: TSocket;
  WSAEventObject: WSAEvent;
  Idx: DWORD;
  EventTotal: DWORD;
  SocketArray: array [
0 ..WSA_MAXIMUM_WAIT_EVENTS  -   1 ] of TSocket;
  WSAEventArray: array [
0 ..WSA_MAXIMUM_WAIT_EVENTS  -   1 ] of WSAEvent;
  WSANetEvents: TWSANetworkEvents;
begin
  inherited;
  EventTotal:
=   0 ;
  FreeOnTerminate:
=  True;

  
// 初始化Winsock
  WSAStartUp($ 202 , WSData);
  
// 创建套接字
  ServerSocket: =  Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  
// 设置LocalAddr的参数
  LocalAddr.sin_family: =  AF_INET;    // IPV4族
  LocalAddr.sin_addr.S_addr: =  INADDR_ANY; // 这里不能写Inet_addr('127.0.0.1'),否则会绑定失败,不清楚原因是什么;
  LocalAddr.sin_port: =  Htons( 1077 );  // Host To Net Short,主机字节顺序转为网络字节顺序
  
// 绑定本机IP地址、端口,绑定之前先设置好LocalAddr的参数
  Bind(ServerSocket, PSOCKADDR(@LocalAddr), SizeOf(LocalAddr));

  
// 创建EventObject
  WSAEventObject: =  WSACreateEvent();
  
// 使用WSAEventSelect模型
  WSAEventSelect(ServerSocket, WSAEventObject, FD_ACCEPT or FD_READ or FD_CONNECT);
  
// 开始监听,最多同时监听5个连接
  Listen(ServerSocket,  5 );

  SocketArray[EventTotal]:
=  ServerSocket;
  WSAEventArray[EventTotal]:
=  WSAEventObject;
  Inc(EventTotal);

  
while  not Terminated  do
  begin
    
// 用WSAWaitForMultipleEvents检测是否有“事件”发生
    Idx: =  WSAWaitForMultipleEvents(EventTotal, @WSAEventArray[ 0 ], False, WSA_INFINITE, False);
    
// 判断发生了什么“事件”——读、写、断开等等
    WSAEnumNetWorkEvents(SocketArray[Idx  -  WSA_WAIT_EVENT_0],
      WSAEventArray[Idx 
-  WSA_WAIT_EVENT_0], @WSANetEvents);

    
if  (WSANetEvents.lNetworkEvents and FD_ACCEPT)  >   0  then  // 如果是Accept事件
    begin
      ClientAddrLen:
=  SizeOf(ClientAddr);
      ClientSocket:
=  Accept(SocketArray[Idx  -  WSA_WAIT_EVENT_0], ClientAddr, ClientAddrLen);

      WSAEventObject:
=  WSACreateEvent();
      WSAEventSelect(ClientSocket, WSAEventObject, FD_ACCEPT or FD_READ);
      SocketArray[EventTotal]:
=  ClientSocket;
      WSAEventArray[EventTotal]:
=  WSAEventObject;
      Inc(EventTotal);
    end;

    
if  (WSANetEvents.lNetworkEvents and FD_READ)  >   0  then  // 如果是Read事件
       if  Recv(SocketArray[Idx  -  WSA_WAIT_EVENT_0], FBuff, SizeOf(FBuff),  0 >   0  then
        Synchronize(ShowRecv);
  end;
end;

procedure TWorkThread.ShowRecv;
begin
  FMemo.Lines.Add(FBuff);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  TWorkThread.Create(Memo1);
end;

end.

 

 

1.WSAEventSelect需要Winsock2.0,可以google搜索Winsock2.pas;

2.使用Bind的时候要注意:LocalAddr.sin_addr.S_addr:= INADDR_ANY;//这里不能写Inet_addr('127.0.0.1'),负责会绑定失败,不清楚原因是什么;

 

原文: http://blog.csdn.net/dropme/archive/2009/09/10/4538553.aspx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值