WSAAsyncSelect model of asynchronous socket programming

Source: Internet
Author: User
Tags bind socket socket error
WSAAsyncSelect Model:


The █ asynchronous Select (WSAAsyncSelect) model is a useful asynchronous I/O model. With this model, the application can be on a socket,

Receives notification of network events based on Windows messages. The specific practice is to call the WSAAsyncSelect function after the good one socket is under construction.

The core of the model is the WSAAsyncSelect function.

█ to use the WSAAsyncSelect model, in an application, you must first create a window with the CreateWindow function, and then provide a window routine function (winproc) for that window. (This is also a disadvantage of wsaasyncselect)

The function prototypes for █wsaasyncselect are as follows:

int WSAAsyncSelect (

__in SOCKET S,

__in HWND hwnd,

__in unsigned int wmsg,

__in Long LEvent

);

The s parameter specifies the socket that we are interested in.

The hWnd parameter specifies a window handle that corresponds to the window in which you want to receive notification messages after a network event occurs.

The wmsg parameter specifies the message that you intend to receive when a network event occurs. The message is posted to the window specified by the HWND window handle.

(Typically, the application needs to set this message to a value larger than the wm_user of windows, avoiding confusion and conflict between the network window messages and the system's predefined standard window messages)

The lEvent parameter specifies a bitmask that corresponds to the combination of a series of network events, and the types of network events that most applications are typically interested in include:

Fd_read, Fd_write, Fd_accept, Fd_connect, Fd_close. Of course, whether to use fd_accept or fd_connect type,

Depends on whether the identity of the application is a client or a server. If the application is interested in multiple network events at the same time, simply perform a simple bitwise OR (or) operation on each type.

You can then assign them to Levent, for example:

WSAASYNCSELTCT (S, Hwnd,wm_socket, Fd_connect | Fd_read | Fd_write | Fd_close);

Explanation: Our application is then able to receive notifications about connection, send, receive, and socket closure for a series of network events on the socket s.

█ Note ①:

Multiple events must be registered at the same time as the socket.

It is also important to note that once an event notification is allowed on a socket, later unless you explicitly call the Closesocket command,

Or the application calls the WSAAsyncSelect for that socket, which changes the type of network event registered, otherwise,

Event notifications are always valid. If you set the Levent parameter to 0, the effect is equivalent to stopping all network event notifications on the socket.

█ Note ②:

if the application calls WSAAsyncSelect for a socket, then the pattern of the socket changes from "locked" to "non-locking".

In this way, if a Winsock function such as WSARecv is called, but there is no data available at that time, it will inevitably cause the call to fail and return a wsaewouldblock error.

To prevent this, the application should rely on the user-defined window message specified by the umsg parameter of WSAAsyncSelect to determine when the network event type occurs on the socket and should not be called blindly.

The Fd_read application wants to receive notifications about whether it is readable so that it can read into the data

The Fd_write application wants to receive notifications about whether it can be written to write data

Fd_accept application wants to receive notifications about incoming connections

Fd_connect application wants to receive notifications with a single connection complete

Fd_close application wants to receive notifications with sockets off

After the █ application successfully invokes WSAAsyncSelect on a socket, it receives a network event notification in the form of a Windows message in the window routine corresponding to the HWND window handle.

The window routines are usually defined as follows:

LRESULT CALLBACK WindowProc (

HWND hwnd,

UINT umsg,

WPARAM WPARAM,

LPARAM LPARAM

);

The HWND parameter specifies the handle of a window that is emitted by the call to the window routine.

the umsg parameter specifies which messages need to be processed. Here we are interested in the message defined in the WSAAsyncSelect invocation.

The WParam parameter specifies the socket on which a network event occurred. If multiple sockets are assigned to this window routine at the same time, the importance of this parameter is displayed.

The lparam parameter contains two important information. Among them, LPARAM's low word (low word) specifies the network events that have occurred, and lparam's high-word (tall word) contains any error codes that may appear.

█ step: After the network event message arrives at a window routine, the application should first check the LPARAM's high-bit to determine if the network error is in.

Here is a special macro: Wsagetselecterror, which can be used to return the error message contained in the high-bit character.

If the application finds that there are no errors on the socket, then it should investigate which network event type it is, and specifically read the lparam low-bit content.

You can now use another special macro:wsagetselectevent, which returns the low-word portion of lparam (that is, fd_).

Such as:

if (Wsagetselecterror (LParam))

Return

Else

{

Switch (wsagetselectevent (lParam))

{

Case Fd_read:

...

Break

Case Fd_write:

...

Break

...

}

}

█ Note ③: How the application handles Fd_write event notifications.

Fd_write notifications are issued only under three conditions:

With connect or wsaconnect, a socket is established for the first time.

With accept or wsaaccept, the socket is accepted later.

If the send, WSASend, sendto, or wsasendto operation fails, a wsaewouldblock error is returned, and the buffer space becomes available.

Therefore, as an application, you should consider yourself bound to emit data on a socket as soon as you receive the first Fd_write message.

The socket error Wsaewouldblock is returned until a send, WSASend, SendTo, or WSASendTo.

After such a failure, another fd_write is used to notify the application to send the data again.

Server side: UINT cserverdlg::threadfun (LPVOID pparam) {cserverdlg* pdlg= (cserverdlg*) Pparam;

	Pdlg->initsock ();
	Sockaddr_in Seradd; Seradd.sin_family=af_inet;
	Af_inet represents the address family, which is the same as the Pf_inet (protocol family) under Windows Seradd.sin_port=htons (5000);
	Seradd.sin_addr.s_addr=addr_any; Pdlg->m_listensock=socket (AF_INET,SOCK_STREAM,IPPROTO_TCP);
		Create socket if (Invalid_socket==pdlg->m_listensock) {AfxMessageBox (_t ("Initialize socket failed"));
	return 0; } if (Socket_error==bind (Pdlg->m_listensock, (sockaddr*) &seradd,sizeof (sockaddr))) {AfxMessageBox (_T ("
		Bind address Failed "));
	return 0;
		} if (Sp_error==listen (Pdlg->m_listensock,somaxconn)) {AfxMessageBox (_t ("Boot listener failed");

	return 0; } wsaasyncselect (Pdlg->m_listensock,pdlg->getsafehwnd (), wm_socket,fd_accept | 
	    Fd_close); When an event of interest occurs, use Windows message Notification//To implement the message in the window procedure. LRESULT cserverdlg::windowproc (UINT message, WPARAM WPARAM, LPARAM LPar AM) {//TODO: In this Add private code and/or Call base class//In Network event WPARAM represents the handle lparam the high point indicates that the error message low indicates the associated network event switch(message)
				{Case Wm_syscommand: {if (Sc_close==wparam) {if (M_listensock) closesocket (M_listensock);
				if (m_clisock) closesocket (M_clisock);
			WSACleanup ();
	 }} break; Case Wm_socket:if (Wsagetasyncerror (lParam))//wsagenselecterror macro Gets whether there is an error here with HiWord (LParam) is also possible {MessageBox (_t
			 ("Network error"));
			 Closesocket (WParam);
		 return 0;
			 } switch (Wsagetselectevent (lParam))//wsagetselectevent Get network events You can also add {} When you define a variable in Lodord {case fd_accept://case
				 {sockaddr_in cliadd;
				 int len=sizeof (SOCKADDR);
				 M_clisock=accept (WParam, (sockaddr*) &cliadd,&len); WSAAsyncSelect (M_clisock,this->getsafehwnd (), Wm_socket,fd_read | Fd_write | Fd_close);
					 The socket also uses WSAAsyncSelect to process if (M_clisock==invalid_socket) {MessageBox (_t ("Receive connection Error"));
				 return 0;
		 }} break;
				 Case Fd_read: {TCHAR bufdata[1024]={0};
				 int flag;
				 Flag=recv (M_clisock, (char*) bufdata,1024,0);
				if (flag==0) {MessageBox (_t ("Connection Disconnected"));
				 return 0;
			 } showmsg (Bufdata);
		 } break; Case Fd_write:wparam=wparam;
		 Do not handle break;
			 Case Fd_close:closesocket (WParam);
			 WSACleanup ();
		 Break
		 Default:break;
}} return Cdialog::windowproc (message, WParam, LParam); The client is basically similar to the server



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.