Winsock Study Notes 4: wsaeventselect Model
Wsaeventselect is similar to wsaasycnselect. The difference is that when there is an "Event" on the socket, an event is passed instead of a Windows message.
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;
// Initialize Winsock
Wsastartup ($ 202 , Wsdata );
// Create socket
Serversocket: = Socket (af_inet, sock_stream, ipproto_tcp );
// Set localaddr Parameters
Localaddr. sin_family: = Af_inet; // IPv4
Localaddr. sin_addr.s_addr: = Inaddr_any; // Inet_addr ('192. 0.0.1 ') cannot be written here; otherwise, the binding will fail and the reason is unknown;
Localaddr. sin_port: = Htons ( 1077 ); // Host to net short, host byte order to network byte order
// Bind the local IP address and port. Set the localaddr parameters before binding.
BIND (serversocket, psockaddr (@ localaddr), sizeof (localaddr);
// Create eventobject
wsaeventobject: = wsacreateevent ();
/// use the wsaeventselect Model
wsaeventselect (serversocket, wsaeventobject, fd_accept or fd_read or fd_connect);
// Start listening, listen to a maximum of five connections
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 );
// Determine what "events" occur-read, write, disconnect, and so on
Wsaenumnetworkevents (socketarray [idx - Wsa_wait_event_0],
Wsaeventarray [idx - Wsa_wait_event_0], @ wsanetevents );
If (wsanetevents. lnetworkevents and fd_accept) > 0 then // for an accept event
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 // For read events
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 requires winsock2.0, which can be searched by Google for winsock2.pas;
2. note the following when using bind: localaddr. sin_addr.s_addr: = inaddr_any; // inet_addr cannot be written here ('2017. 0.0.1 '). The binding will fail. It is unclear why;
Original article: http://blog.csdn.net/dropme/archive/2009/09/10/4538553.aspx