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'),负责会绑定失败,不清楚原因是什么;