//////////////////////////////////////// //////////////////////////////////
// Complete the port
//
//
//////////////////////////////////////// //////////////////////////////////
# Include "stdafx. H"
# Include <windows. h>
# Include <winsock2.h>
# Include <stdio. h>
Int initsock ();
DWORD winapi serworkthread (lpvoid completionport );
// Perhandledata
Typedef struct _ per_handle_data
{
Socket socket;
Sockaddr_in clientaddr;
} Per_handle_data, * lpper_handle_data;
// Per Io operation data
Typedef struct _ per_io_operation_data
{
Overlapped;
Wsabuf databuf;
Char buffer [8192];
DWORD bytessend;
DWORD bytesrecv;
} Per_io_operation_data, * lpper_io_operation_data;
Int main (INT argc, char * argv [])
{
Handle hcompletionport;
System_info sysinfo;
Int I = 0;
Socket listen;
Socket accept;
Sockaddr_in inetaddr;
DWORD flags = 0;
DWORD recvbytes = 0;
Sockaddr_in saremote;
Int saremotelen = sizeof (saremote );
Lpper_handle_data perhandledata = NULL;
Lpper_io_operation_data periooperationdata = NULL;
If (! Initsock ()){
Printf ("initsock error! /N ");
Return 0;
}
// The created port
Hcompletionport = createiocompletionport (invalid_handle_value, null, 0, 0 );
If (hcompletionport = NULL ){
Printf ("creatae completionport Error !! /N ");
Return 0;
}
// Create a worker thread. The number of threads is consistent with the number of CPUs.
// The worker thread provides services for port completion when the IO request arrives.
Getsysteminfo (& sysinfo );
For (I = 0; I <(INT) sysinfo. dwnumberofprocessors; I ++)
{
Handle hthread;
Hthread = createthread (null, 0, serworkthread, hcompletionport, 0, null );
If (hthread = NULL ){
Printf ("createthread fail! ");
}
Closehandle (hthread );
}
// Note that the socket here is TCP
Listen = wsasocket (af_inet, sock_stream, 0, null, 0, wsa_flag_overlapped );
If (Listen = invalid_socket ){
Printf ("Listen's socket error! /N ");
Return 0;
}
Inetaddr. sin_family = af_inet;
Inetaddr. sin_port = htons (5010 );
Inetaddr. sin_addr.s_un.s_addr = htonl (inaddr_any );
If (BIND (Listen, (sockaddr *) & inetaddr,
Sizeof (sockaddr) = socket_error ){
Printf ("BIND error/N ");
Return 0;
}
If (Listen, 5) = socket_error) {// note the second parameter
Printf ("Listen error/N ");
Return 0;
}
While (true)
{
Accept = wsaaccept (Listen, (sockaddr *) & saremote, & saremotelen, null, null );
If (accept = socket_error ){
Printf ("Accept error/N ");
}
// Set per-handle data
Perhandledata = (lpper_handle_data) globalalloc (gptr, sizeof (per_handle_data ));
If (perhandledata = NULL ){
Printf ("globalalloc momery error! ");
Return 0;
}
Printf ("socket Number % d connected./N", accept );
Perhandledata-> socket = accept;
Memcpy (& perhandledata-> clientaddr, & saremote, saremotelen );
// Perhandledata contains other socket-related information
If (createiocompletionport (handle) Accept, hcompletionport, (DWORD) perhandledata, 0) = NULL ){
Printf ("createcompletionport error! ");
Return 0;
}
Periooperationdata = (lpper_io_operation_data) globalalloc (
Gptr, sizeof (per_io_operation_data ));
Zeromemory (& (periooperationdata-> overlapped), sizeof (overlapped ));
Periooperationdata-> bytessend = 0;
Periooperationdata-> bytesrecv = 0;
Periooperationdata-> databuf. Buf = periooperationdata-> buffer;
Periooperationdata-> databuf. Len = 8192;
Flags = 0;
If (wsarecv (accept, & (periooperationdata-> databuf), 1, & recvbytes, & flags,
& (Periooperationdata-> overlapped), null) = socket_error ){
If (wsagetlasterror ()! = Error_io_pending)
{
Printf ("wsarecv () failed with error % d/N", wsagetlasterror ());
Return;
}
}
}
}
Int initsock (void)
{
Word wversionrequested;
Wsadata;
Int err;
Wversionrequested = makeword (2, 2 );
Err = wsastartup (wversionrequested, & wsadata );
If (Err! = 0 ){
Return 0;
}
If (lobyte (wsadata. wversion )! = 2 |
Hibyte (wsadata. wversion )! = 2 ){
Wsacleanup ();
Return 0;
}
Return 1;
}
DWORD winapi serworkthread (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)
{
// Obtain the status of the completed port queue. Here, the information after I/O operations is passed into perhandledata and periodata.
If (getqueuedcompletionstatus (completionport, & bytestransferred,
(Lpdword) & perhandledata, (lpoverlapped *) & periodata, infinite) = 0)
{
Printf ("getqueuedcompletionstatus failed with error % d/N", getlasterror ());
Return 0;
}
// Bytestransferred the actual number of characters received/transmitted after an IO operation is completed
If (bytestransferred = 0) // The data has been sent
{
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;
}
If (periodata-> bytesrecv = 0)
{
Periodata-> bytesrecv = bytestransferred;
Periodata-> bytessend = 0;
}
Else
{
Periodata-> bytessend + = bytestransferred;
}
If (periodata-> bytesrecv> periodata-> bytessend)
{
Zeromemory (& (periodata-> overlapped), sizeof (overlapped ));
Periodata-> databuf. Buf = periodata-> buffer + periodata-> bytessend;
Periodata-> databuf. Len = periodata-> bytesrecv-periodata-> bytessend;
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;
}
}
}
Else
{
Periodata-> bytesrecv = 0;
Flags = 0;
Zeromemory (& (periodata-> overlapped), sizeof (overlapped ));
Periodata-> databuf. Len = 8192;
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;
}
}
Else
{// Print the received message
Printf ("% s", & periodata-> databuf );
}
}
}
}