unit10 winsock messagedriven - 中国传媒大学 计算...
TRANSCRIPT
Windows SocketMessage-Driven/WSAAsyncSelect Model
Prof. Lin WeiguoCopyleft © 2009~2017, School of Computing, CUC
Dec 2017
Note
Advanced Windows Network Programming
} You should not assume that an example in this presentation is complete. Items may have been selected for illustration. It is best to get your code examples directly from the textbook and modify them to work. Use the lectures to understand the general principles.
2 2017/12/5
Windows Message Processing
Advanced Windows Network Programming
} Windows Messages} Windows-based applications are event-driven. They do not
make explicit function calls to obtain input. Instead, they wait for the system to pass input to them.
} The system passes input to a window procedure in the form of messages. Messages are generated by both the system and applications.
} How a Single-Threaded Program Processes Messages
3 2017/12/5
MSG message;while (::GetMessage(&message, NULL, 0, 0)) {
::TranslateMessage(&message);::DispatchMessage(&message);
}
Message-Driven I/O
Advanced Windows Network Programming
} Windows specific variant of non-blocking I/O} The I/O functions continue to run in the background
and the program is notified if:} I/O operations are completed} I/O operations can be executed} An I/O error occurred
} Notification is done using window messages. Each Windows application (must have a GUI) has a message loop that processes window messages and other messages} When we use Message-Driven I/O, we define a custom
message that is sent to the message loop to notify us about the status of IO operations.
5 2017/12/5
Win32 API Message Processing
Advanced Windows Network Programming
} Every Window element has an associated Window Procedure -registered when the Window is created, for processing messages.
7 2017/12/5
LRESULT WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam ){
switch (iMessage){
case WM_CREATE:DoCreate();break;
case WM_PAINT:Paint();break;
case WM_DESTROY:PostQuitMessage( 0 );break;
default:return DefWindowProc( hWnd, iMessage, wParam, lParam );
}return 0;
}
MFC: Message Mapping Macro
Advanced Windows Network Programming8 2017/12/5
// Example for BEGIN_MESSAGE_MAPBEGIN_MESSAGE_MAP( CMyWindow, CFrameWnd )
ON_WM_PAINT()ON_COMMAND( IDM_ABOUT, OnAbout )
END_MESSAGE_MAP( )
BEGIN_MESSAGE_MAP(CComputeDlg, CDialog)ON_BN_CLICKED(IDC_START, &CComputeDlg::OnBnClickedStart)ON_BN_CLICKED(IDC_CANCEL, &CComputeDlg::OnBnClickedCancel)ON_WM_TIMER()
END_MESSAGE_MAP()
Create Message-driven Socket
Advanced Windows Network Programming
} Winsock provides a useful asynchronous I/O model that allows an application to receive Windows message–based notification of network events on a socket. This is accomplished by calling the WSAAsyncSelect function after creating a socket.
} Create Message-driven Socket } Step 1: Create a socket as usual.} Step 2: Use the WSAAsyncSelect function to turn the socket
into a message-driven socket.
9 2017/12/5
Note: The WSAAsyncSelect and WSAEventSelect models provide asynchronous notification of the capability to read or write data. It does not provide asynchronous data transfer like the overlapped and completion port models.
WSAAsyncSelect
Advanced Windows Network Programming
} The WSAAsyncSelect function requests Windows message-based notification of network events for a socket.
10 2017/12/5
int WSAAsyncSelect(__in SOCKET s,__in HWND hWnd,__in unsigned int wMsg,__in long lEvent
);
Parameterss [in]: A descriptor that identifies the socket for which event notification is required.hWnd [in] A handle that identifies the window that will receive a message when a network event occurs.wMsg [in] A message to be received when a network event occurs.lEvent [in] A bitmask that specifies a combination of network events in which the application is interested.
Note: socket() creates a socket in blocking mode,WSAAsyncSelect() turns it to non-blocking mode.
User-Defined Winsock Message
Advanced Windows Network Programming
} Declare user message ID
} Declare message handling function in the .h file
} Map the message to the handling function in .cpp file
} Implement the message handling functon in .cpp file
11 2017/12/5
#define WM_WINSOCK (WM_USER + 100)
BEGIN_MESSAGE_MAP(CMYDlg, CDialog)…
ON_MESSAGE(WM_WINSOCK, OnWinsock)END_MESSAGE_MAP()
…afx_msg LRESULT OnWinsock(WPARAM wParam, LPARAM lParam);DECLARE_MESSAGE_MAP()
LRESULT CMyDlg::OnWinsock(WPARAM wParam, LPARAM lParam){ ... return 0; }
Posting winsock message
Advanced Windows Network Programming13 2017/12/5
int CMyDlg::StartMsgDrivenReceive(){
// ...int err = WSAAsyncSelect ( socket,
m_hWnd, // Window handle, from MFC’s CWindowWM_WINSOCK,FD_READ | FD_ACCEPT | FD_CLOSE);
if (err != 0){
afxMessageBox("WSAAsyncSelect() failed!“);// ...
}// ...
}
Network Event Types for the WSAAsyncSelect Function
Advanced Windows Network Programming
Event Type Meaning
FD_READ The application wants to receive notification of readiness for reading.
FD_WRITE The application wants to receive notification of readiness for writing.
FD_OOB The application wants to receive notification of the arrival of OOB data.
FD_ACCEPT The application wants to receive notification of incoming connections.
FD_CONNECT The application wants to receive notification of a completed connection or a multipoint join operation.
FD_CLOSE The application wants to receive notification of socket closure.
FD_QOS The application wants to receive notification of socket QOS changes.
FD_GROUP_QOS The application wants to receive notification of socket group QOS changes (reserved for future use with socket groups).
FD_ROUTING_INTERFACE_CHANGE
The application wants to receive notification of routing interface changes for the specified destination(s).
FD_ADDRESS_LIST_CHANGE
The application wants to receive notification of local address list changes for the socket's protocol family.
14 2017/12/5
Setting the Event parameter
Advanced Windows Network Programming15 2017/12/5
//a typical clientWSAAsyncSelect(s, m_hwnd, WM_SOCKET,
FD_CONNECT │ FD_READ │ FD_WRITE │ FD_CLOSE);
WSAAsyncSelect(Sockfd,m_hwnd,WM_SOCKET,FD_READ|FD_WRITE); // Activate both read & write.
WSAAsyncSelect(Sockfd, hMyWindow, WM_SOCKET,
0 // Disable all events.);
Server side WSAAsyncSelect
Advanced Windows Network Programming16 2017/12/5
SOCKET Listen = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);// Bind the socket to port 5150 and begin listening for connectionsInternetAddr.sin_family = AF_INET;InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);InternetAddr.sin_port = htons(5150);
bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr));
// Set up window message notification on// the new socket using the WM_SOCKET define above
WSAAsyncSelect(Listen, Window, WM_SOCKET, FD_ACCEPT │ FD_CLOSE);
listen(Listen, 5);
// Translate and dispatch window messages// until the application terminateswhile (1) {// ...
Processing Winsock Message
Advanced Windows Network Programming17 2017/12/5
LRESULT CMyDlg::OnWinsock(WPARAM wParam, LPARAM lParam){
SOCKET sock = (SOCKET) wParam;int event = WSAGETSELECTEVENT(lParam);int WsaErr = WSAGETSELECTERROR(lParam);
// Determine whether an error occurred on the socket by using the WSAGETSELECTERROR() macroif (WsaErr) { closesocket( sock ); return 0; }
switch(event)// Determine what event occurred on the socket{
case FD_ACCEPT:OnAccept( sock ); break; // Accept an incoming connection
case FD_READ:OnRead( sock ); break; // Receive data from the socket in wParam
case FD_WRITE:OnWrite( sock ); break; // The socket in wParam is ready for sending data
case FD_CLOSE:closesocket( sock); break; // The connection is now closed
}return 0;
}
Processing Winsock Event:OnAccept()
Advanced Windows Network Programming18 2017/12/5
Void CMyDlg::OnAccept(SOCKET mysocket){
SOCKET AcceptedSock = accept(mysocket, NULL, NULL);if (total_conn >= MAX_CLIENT_NUM) //close if more than MAX client number{
closesocket(AcceptedSock); return;}ClientSock[CurConn].Sock=AcceptedSock; //save the new socket to the connected list
// Prepare accepted socket for read, write, and close notificationWSAAsyncSelect(AcceptedSock, m_hWnd, WM_SOCKET, FD_READ │ FD_WRITE │ FD_CLOSE);…
}
Void CMyDlg::OnRead(SOCKET mysocket){
if (mysocket==ServerSock_UDP) //UDP Echo{ recvfrom(…); sendto(…);}
else if (mysocket!=ServerSock) //TCP Time server{ recv(…); send(…);}
}
Alternative way for processing User-Defined Message
Advanced Windows Network Programming
} Step 1:} Select the dialog class in the
Class view.} Step 2:
} Go to Properties view.} Click the icon for overrides (a
green cube in VS.NET 2008).} Find “Window Proc” in the
list.} Open the drop-list and select
“<Add> Window Proc”.
19 2017/12/5
Alternative way for processing User-Defined Message
Advanced Windows Network Programming
} Step 3:} Add code to filter the defined custom message for network
events
20 2017/12/5
// Override MFC's Window procedure to process the Winsock messages.LRESULT CMyDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam){
// TODO: Add your specialized code here and/or call the base classif (message == WM_WINSOCK) {
int event = WSAGETSELECTEVENT(lParam);int wsaerr = WSAGETSELECTERROR(lParam);switch (event) {
case FD_READ : OnRead(); return 0;case FD_ACCEPT : OnAccept(); return 0;case FD_CLOSE : OnClose(); return 0;
}}return CDialog::WindowProc(message, wParam, lParam);
}
Winsock Event Triggering
Advanced Windows Network Programming
} Edge-Triggered v.s. Level Triggered} Re-enabling functions
21 2017/12/5
Winsock Event Triggering
Advanced Windows Network Programming
} Level Trigger example: FD_READ
22 2017/12/5
Winsock Event Triggering
Advanced Windows Network Programming
} Edge Trigger example: FD_WRITE
23 2017/12/5
On Write
Advanced Windows Network Programming24 2017/12/5
case FD_WRITE: // write event{
while(TRUE){// read from a file into packet.data.in.read((char*)&packet.data, MAX_PACKET_SIZE);
// sending dataif (send(wparam, (char*)(&packet), sizeof(PACKET), 0) == SOCKET_ERROR)
{if (WSAGetLastError() == WSAEWOULDBLOCK){
break; // socket internal buffer full} else // other errors{
// output error message, and return.CleanUp();return(0);
}}
}} break;
summary of events and conditions for asynchronous notification message.
Advanced Windows Network Programming
} FD_READ: 1. When WSAAsyncSelect is called, if there is data currently available to receive.2. When data arrives, if FD_READ is not already posted.3. After recv or recvfrom is called, with or without MSG_PEEK, if data is still
available to receive.
} FD_WRITE: 1. When WSAAsyncSelect called, if a send or sendto is possible.2. After connect or accept called, when connection established.3. After send or sendto fail with WSAEWOULDBLOCK, when send or sendto
are likely to succeed.4. After bind on a connectionless socket. FD_WRITE may or may not occur at
this time (implementation-dependent). In any case, a connectionless socket is always writeable immediately after a bind operation.
25 2017/12/5
summary of events and conditions for asynchronous notification message.
Advanced Windows Network Programming
} FD_ACCEPT:1. When WSAAsyncSelect called, if there is currently a connection request available to accept.
2. When a connection request arrives, if FD_ACCEPT not already posted.3. After accept called, if there is another connection request available to accept.
} FD_CONNECT:1. When WSAAsyncSelect called, if there is currently a connection
established.2. After connect called, when connection is established, even when connect
succeeds immediately, as is typical with a datagram socket.3. After calling WSAJoinLeaf, when join operation completes.4. After connect, WSAConnect, or WSAJoinLeaf was called with a
nonblocking, connection-oriented socket. The initial operation returned with a specific error of WSAEWOULDBLOCK, but the network operation went ahead. Whether the operation eventually succeeds or not, when the outcome has been determined, FD_CONNECT happens. The client should check the error code to determine whether the outcome was successful or failed.
26 2017/12/5
summary of events and conditions for asynchronous notification message.
Advanced Windows Network Programming
} FD_CLOSE: Only valid on connection-oriented sockets (for example, SOCK_STREAM)1.When WSAAsyncSelect called, if socket connection has been closed.2.After remote system initiated graceful close, when no data currently
available to receive (Be aware that, if data has been received and is waiting to be read when the remote system initiates a graceful close, the FD_CLOSE is not delivered until all pending data has been read).
3.After local system initiates graceful close with shutdown and remote system has responded with "End of Data" notification (for example, TCP FIN), when no data currently available to receive.
4.When remote system terminates connection (for example, sent TCP RST), and lParam will contain WSAECONNRESET error value.
27 2017/12/5
Note FD_CLOSE is not posted after closesocket is called.
Summary
Advanced Windows Network Programming
} The WSAAsyncSelect model offers many advantages} foremost is the capability to handle many connections
simultaneously without much overhead, unlike the select model's requirement of setting up the fd_set structures.
} The disadvantages are } having to use a window if your application requires no
windows (such as a service or console application). } Also, having a single window procedure to service all the
events on thousands of socket handles can become a performance bottleneck (meaning this model doesn't scale very well).
29 2017/12/5
references
Advanced Windows Network Programming
} Programming With Microsoft Visual C++ NET 6th Ed. - George/Kruglinski Shepherd. 2002
} Network Programming for Microsoft Windows , 2nd Ed. -Anthony Jones, Jim Ohlund. 2002.
} MSDN: WSAAsyncSelect, WSAEventSelect Function} CUHK Ieg4180: Network Software Design and Programming} Drew Sikora, Programming with Asynchronous Sockets,
GameDev.net, 2/1/2001} http://www.sockets.com/err_lst1.htm#WSAEWOULDBLOCK} The C10K problem, http://www.kegel.com/c10k.html
30 2017/12/5