Example of completed port (iocp)

Source: Internet
Author: User

# 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;
}
}
}
}
}

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.