文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>WinSock学习笔记4:WSAEventSelect模型

WinSock学习笔记4:WSAEventSelect模型

时间:2010-09-28  来源:tc310

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
相关阅读 更多 +
排行榜 更多 +
泡龙大闯关安卓版

泡龙大闯关安卓版

冒险解谜 下载
割草派对安卓版

割草派对安卓版

飞行射击 下载
堡垒攻防战安卓版

堡垒攻防战安卓版

飞行射击 下载