# Include <winsock2.h>
# Include <windows. h>
# Include <stdio. h>
# Define Port 6000
# Define data_bufsize 8192
# Pragma comment (Lib, "ws2_32 ")
Typedef struct // This is the data filling, which is a custom data structure of the data.
// It is not much different from the wm_data, but it is an overlapped structure of the old fortress,
{
Overlapped;
Wsabuf databuf;
Char buffer [data_bufsize];
DWORD bytessend; // Number of sent bytes
DWORD bytesrecv;
} Per_io_operation_data, * lpper_io_operation_data;
Typedef struct
{
Socket socket;
} Per_handle_data, * lpper_handle_data;
DWORD winapi serverworkerthread (lpvoid completionportid );
Void main (void)
{
Sockaddr_in internetaddr;
Socket listen;
Socket accept;
Handle completionport;
System_info systeminfo;
Lpper_handle_data perhandledata;
Lpper_io_operation_data periodata;
Int I;
DWORD recvbytes;
DWORD flags;
DWORD threadid;
Wsadata;
DWORD ret;
If (ret = wsastartup (0x0202, & wsadata ))! = 0)
{
Printf ("wsastartup failed with error % d \ n", RET );
Return;
}
//
// Set up the port twice. This is the first call. Why? I want to ask you
//
If (completionport = createiocompletionport (invalid_handle_value, null, 0, 0) = NULL)
{
Printf ("createiocompletionport failed with error: % d \ n", getlasterror ());
Return;
}
// The old sub-API.
Getsysteminfo (& systeminfo );
// If two CPUs are found, open a double thread.
For (I = 0; I <systeminfo. dwnumberofprocessors * 2; I ++)
{
Handle threadhandle;
//
// The finished port is mounted to the thread, just as the pipe connects the two ends of Data filling and reading,
//
If (threadhandle = createthread (null, 0, serverworkerthread, completionport,
0, & threadid) = NULL)
{
Printf ("createthread () failed with error % d \ n", getlasterror ());
Return;
}
Closehandle (threadhandle );
}
//
// Start a listener socket.
//
If (Listen = wsasocket (af_inet, sock_stream, 0, null, 0,
Wsa_flag_overlapped) = invalid_socket)
{
Printf ("wsasocket () failed with error % d \ n", wsagetlasterror ());
Return;
}
Internetaddr. sin_family = af_inet;
Internetaddr. sin_addr.s_addr = htonl (inaddr_any );
Internetaddr. sin_port = htons (port );
If (BIND (Listen, (psockaddr) & internetaddr, sizeof (internetaddr) = socket_error)
{
Printf ("BIND () failed with error % d \ n", wsagetlasterror ());
Return;
}
If (Listen, 5) = socket_error)
{
Printf ("Listen () failed with error % d/N", wsagetlasterror ());
Return;
}
//
// When the listener port is opened, the loop starts here. Once a socket is connected, wsaaccept creates a socket,
// The socket is connected to the completed port again,
//
// Hey, The createxxx function is called the second time after the port is completed. Why is it more profound for people to think about,
// This set of paths has to come twice,
// Port completionport and accept socket are mounted,
//
While (true)
{
// Wait until the main thread runs here, but the thread starts working,
If (accept = wsaaccept (Listen, null, 0) = socket_error)
{
Printf ("wsaaccept () failed with error % d \ n", wsagetlasterror ());
Return;
}
If (perhandledata = (lpper_handle_data) globalalloc (gptr, sizeof (per_handle_data) = NULL)
{
Printf ("globalalloc () failed with error % d \ n", getlasterror ());
Return;
}
Perhandledata-> socket = accept;
//
// Connect this end to the complete port completionport
// Just like you have connected the funnel to the pipe port and you are about to fill in data
//
If (createiocompletionport (handle) Accept, completionport, (DWORD) perhandledata,
0) = NULL)
{
Printf ("createiocompletionport failed with error % d \ n", getlasterror ());
Return;
}
//
// Clear the data structure of the pipe and prepare to fill it with data
//
If (periodata = (lpper_io_operation_data) globalalloc (gptr, sizeof (per_io_operation_data) = NULL)
{
Printf ("globalalloc () failed with error % d \ n", getlasterror ());
Return;
}
Zeromemory (& (periodata-> overlapped), sizeof (overlapped ));
Periodata-> bytessend = 0;
Periodata-> bytesrecv = 0;
Periodata-> databuf. Len = data_bufsize;
Periodata-> databuf. Buf = periodata-> buffer;
Flags = 0;
//
// When accept receives the data, it is put into periodata, and periodata is retrieved through the function in the thread,
//
If (wsarecv (accept, & (periodata-> databuf), 1, & recvbytes, & flags,
& (Periodata-> overlapped), null) = socket_error)
{
If (wsagetlasterror ()! = Error_io_pending)
{
Printf ("wsarecv () failed with error % d \ n", wsagetlasterror ());
Return;
}
}
}
}
//
// Once the thread is called, it will always loop in it,
// Note that the input port is the complete port, which is used to retrieve the data in the pipe.
//
DWORD winapi serverworkerthread (lpvoid completionportid)
{
Handle completionport = (handle) completionportid;
DWORD bytestransferred;
Lpoverlapped overlapped;
Lpper_handle_data perhandledata;
Lpper_io_operation_data periodata;
DWORD sendbytes, recvbytes;
DWORD flags;
While (true)
{
//
// Check the data Buf area of the completed port. Is the data available?
// The description of this function parameter is required,
// Periodata is the data flowing from the pipe,
// Perhandledata is also taken from the pipe. When is it inserted,
// When createiocompletionport is created for 2nd times
If (getqueuedcompletionstatus (completionport, & bytestransferred,
(Lpdword) & perhandledata, (lpoverlapped *) & periodata, infinite) = 0)
{
Printf ("getqueuedcompletionstatus failed with error % d \ n", getlasterror ());
Return 0;
}
// Check if data transfer is complete
If (bytestransferred = 0)
{
Printf ("Closing socket % d \ n", perhandledata-> socket );
If (closesocket (perhandledata-> socket) = socket_error)
{
Printf ("closesocket () failed with error % d \ n", wsagetlasterror ());
Return 0;
}
Globalfree (perhandledata );
Globalfree (periodata );
Continue;
}
// Check if there is data in the pipe? = 0. That is the data you just received.
If (periodata-> bytesrecv = 0)
{
Periodata-> bytesrecv = bytestransferred;
Periodata-> bytessend = 0;
}
Else,
{
Periodata-> bytessend + = bytestransferred;
}
// Is the data not sent? Continue sending
If (periodata-> bytesrecv> periodata-> bytessend)
{
Zeromemory (& (periodata-> overlapped), sizeof (overlapped); // clear 0 to prepare for sending
Periodata-> databuf. Buf = periodata-> buffer + periodata-> bytessend;
Periodata-> databuf. Len = periodata-> bytesrecv-periodata-> bytessend;
// One byte sends data out
If (wsasend (perhandledata-> socket, & (periodata-> databuf), 1, & sendbytes, 0,
& (Periodata-> overlapped), null) = socket_error)
{
If (wsagetlasterror ()! = Error_io_pending)
{
Printf ("wsasend () failed with error % d \ n", wsagetlasterror ());
Return 0;
}
}
Printf ("Send: % s \ n", periodata-> buffer );
}
Else
{
Periodata-> bytesrecv = 0;
Flags = 0;
Zeromemory (& (periodata-> overlapped), sizeof (overlapped ));
Periodata-> databuf. Len = data_bufsize;
Periodata-> databuf. Buf = periodata-> buffer;
If (wsarecv (perhandledata-> socket, & (periodata-> databuf), 1, & recvbytes, & flags,
& (Periodata-> overlapped), null) = socket_error)
{
If (wsagetlasterror ()! = Error_io_pending)
{
Printf ("wsarecv () failed with error % d \ n", wsagetlasterror ());
Return 0;
}
}
}
}
}