/// Overlap I/O model implemented by completion routine
/// Asynchronous Io Model
/// It is much easier to use the completion routine to implement overlapping I/O than to use Event Notification. In this model, the main thread only keeps accepting connections.
/// The secondary thread determines whether a new client connection is established. If yes, it activates
/// Asynchronous wsarecv operation, and then call sleepex to make the thread in a warning wait state so that after I/O is complete
/// Completionroutine can be called by the kernel. If the auxiliary thread does not call sleepex, after the kernel completes an I/O operation,
/// The completion routine cannot be called (because the execution of the completion routine should be within the same thread as the code that activated the wsarecv asynchronous operation ).
/// The implementation code in the completion routine is relatively simple. It extracts the received data and sends the data to the client intact,
/// Re-activate another wsarecv asynchronous operation.
/// Note that "trailing data" is used here ".
/// When we call wsarecv, The lpoverlapped parameter actually points to a much larger structure than per_io_operation_data,
/// In addition to wsaoverlapped, this structure is also appended with the Buffer structure information, as well as important information such as client sockets.
/// In this way, the parameter lpoverlapped in the completion routine not only obtains the wsaoverlapped structure,
/// Important information such as the client socket and the received data buffer is also trailing. This C language technique will be used when I introduce the port later.
//////////////////////////////////////// //////////////////////////////////
//////////////////////////////////////// //////////////////////////////////
// Open the envelope ---- pull out the letter paper ---- read the letter ---- reply to the letter ==> complete the routine
/// After Chen receives a new letter, the general procedure is: open the envelope, pull out the letter paper, read the letter, and reply to the letter.
///... To further reduce the burden on users, Microsoft has developed a new technology: users only need to tell Microsoft
/// Operation steps: the Microsoft Mail will follow these steps to process the mail. You no longer need to personally split/read/reply! Lao Chen
/// I have finally lived a petty asset!
//////////////////////////////////////// //////////////////////////////////
# Pragma once
# Include <winsock2.h>
# Include <stdio. h>
# Define Port 5150
# Define msgsize 1024
# Pragma comment (Lib, "ws2_32.lib ")
Typedef struct
{
Wsaoverlapped overlap;
Wsabuf buffer;
Char szmessage [msgsize];
DWORD numberofbytesrecvd;
DWORD flags;
Socket sclient;
} Per_io_operation_data, * lpper_io_operation_data;
DWORD winapi workerthread (lpvoid );
Void callback completionroutine (DWORD, DWORD, lpwsaoverlapped, DWORD); // corresponding completion routine function
Socket g_snewclientconnection;
Bool g_bnewconnectionarrived = false;
Int main ()
{
Wsadata;
Socket slisten;
Sockaddr_in local, client;
DWORD dwthreadid;
Int iaddrsize = sizeof (sockaddr_in );
// Initialize Windows Socket Library
Wsastartup (0x0202, & wsadata );
// Create listening socket
Slisten = socket (af_inet, sock_stream, ipproto_tcp );
// Bind
Local. sin_addr.s_un.s_addr = htonl (inaddr_any );
Local. sin_family = af_inet;
Local. sin_port = htons (port );
BIND (slisten, (struct sockaddr *) & Local, sizeof (sockaddr_in ));
// Listen
Listen (slisten, 3 );
// Create worker thread
Createthread (null, 0, workerthread, null, 0, & dwthreadid );
While (true)
{
// Accept a connection
// The writing method here must be correct.
G_snewclientconnection = accept (slisten, (struct sockaddr *) & client, & iaddrsize );
G_bnewconnectionarrived = true;
Printf ("accepted client: % s: % d/N", inet_ntoa (client. sin_addr), ntohs (client. sin_port ));
}
}
DWORD winapi workerthread (lpvoid lpparam) {lpper_io_operation_data lpperiodata = NULL; while (true) {If (bytes) {// launch an asynchronous operation for new arrived connection lpperiodata = (bytes) heapalloc (getprocessheap (), heap_zero_memory, sizeof (per_io_operation_data); lpperiodata-> buffer. len = msgsize; lpperiodata-> buffer. buf = lpperiodata-> szmessage; lp Periodata-> sclient = bytes; wsarecv (lpperiodata-> sclient, & lpperiodata-> buffer, 1, & lpperiodata-> bytes, & lpperiodata-> flags, & lpperiodata-> overlap, completionroutine); // note that a callback function is registered with the system, which calls g_bnewconnectionarrived = false;} sleepex (1000, true) when the received data is complete );} return 0;} void callback completionroutine (DWORD dwerror, DWORD cbtransferred, lpwsaoverlapped lpoverlapped, DWORD dwflags) {// note this sentence. Convert lpoverlapped of the lpwsaoverlapped type into lpper_io_operation_data lpperiodata = (bytes) lpoverlapped; If (dwerror! = 0 | cbtransferred = 0) {// connection was closed by client closesocket (lpperiodata-> sclient); heapfree (getprocessheap (), 0, lpperiodata );} else {lpperiodata-> szmessage [cbtransferred] = '/0'; send (lpperiodata-> sclient, lpperiodata-> szmessage, cbtransferred, 0 ); // launch another Asynchronous Operation memset (& lpperiodata-> overlap, 0, sizeof (wsaoverlapped); lpperiodata-> buffer. len = msgsize; lpperiodata-> buffer. buf = lpperiodata-> szmessage; wsarecv (lpperiodata-> sclient, & lpperiodata-> buffer, 1, & lpperiodata-> Accept, & lpperiodata-> flags, & lpperiodata-> overlap, completionroutine );}}