Socket programming Summary (2)

Source: Internet
Author: User

Of course, the TCP model also includes the Event Selection Model.
It is to set all network events and events defined in one of our programs.
This has its advantages and may allow us to better write a thread for management.
Receive and send.
Now let's talk about a complete port model.

Complete Port

A completion port is actually a notification queue, and the operating system will send notifications of completed overlapping I/O requests.
Put it in. When an I/O operation is completed, a worker thread that can process the operation result
You will receive a notification. After a socket is created, it can be closed with a complete port at any time.
.
 
Steps:
1. Create an empty completion port;
2. Obtain the number of CPUs on the local machine;
3. Enable the CPU * two working threads (also known as the thread pool), all waiting for the Completion package of the completion port;
4. Create a TCP listening socket and use the event state to create a listening thread;
5. When a connection enters, save the client socket to a key defined by ourselves,
And associate it with the created port;
6. Use the wsarecv and wsasend functions to deliver some requests. This uses overlapping I/O methods;
7. Repeat 5 ~ 6;

Note: 1. When receiving and sending data packets in overlapping I/O mode, the request must be shipped.
Characteristics of their architecture
2. Some internal models of the system are used to complete the port, so we only need to call it in a certain order.
Yes.
3. When the port is used, when there are thousands of users connected, it can
This ensures that the performance is not reduced.

# Include <winsock2.h>
# Include <windows. h>
# Include <stdio. h>

# Define Port 5150
# Define data_bufsize 8192

// Key items
Typedef struct
{
Overlapped;
Wsabuf databuf;
Char buffer [data_bufsize];
DWORD bytessend;
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;
}

// Open an empty completion port

If (completionport = createiocompletionport (invalid_handle_value, null, 0, 0) = NULL)
{
Printf ("createiocompletionport failed with error: % d/N", getlasterror ());
Return;
}

// Determine how many processors are on the system.

Getsysteminfo (& systeminfo );

// Enable two times the number of CPUs

For (I = 0; I <systeminfo. dwnumberofprocessors * 2; I ++)
{
Handle threadhandle;

// Create a server worker thread and pass the completion port to the thread.

If (threadhandle = createthread (null, 0, serverworkerthread, completionport,
0, & threadid) = NULL)
{
Printf ("createthread () failed with error % d/N", getlasterror ());
Return;
}

// Close the thread handle
Closehandle (threadhandle );
}

// Open a server 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;
}

// Start receiving connections from the client

While (true)
{
If (accept = wsaaccept (Listen, null, 0) = socket_error)
{
Printf ("wsaaccept () failed with error % d/N", wsagetlasterror ());
Return;
}

// Create a key item to save the information of this client. The overlapping structure of the received and sent by the user,
// There is also a buffer in use
If (perhandledata = (lpper_handle_data) globalalloc (gptr,
Sizeof (per_handle_data) = NULL)
{
Printf ("globalalloc () failed with error % d/N", getlasterror ());
Return;
}

// Associate the accepted socket with the original completion port.

Printf ("socket Number % d connected/N", accept );
Perhandledata-> socket = accept;

// Associate the key item with the created port.
If (createiocompletionport (handle) Accept, completionport, (DWORD) perhandledata,
0) = NULL)
{
Printf ("createiocompletionport failed with error % d/N", getlasterror ());
Return;
}

// Post a receipt. This function is required for receiving a receipt.

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;
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;
}
}
}
}
// Working thread
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)
{
// A message is sent to the completed port.
If (getqueuedcompletionstatus (completionport, & bytestransferred,
(Lpdword) & perhandledata, (lpoverlapped *) & periodata, infinite) = 0)
{
Printf ("getqueuedcompletionstatus failed with error % d/N", getlasterror ());
Return 0;
}

// Is someone exiting?

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

//

If (periodata-> bytesrecv = 0)
{
Periodata-> bytesrecv = bytestransferred;
Periodata-> bytessend = 0;
}
Else
{
Periodata-> bytessend + = bytestransferred;
}

If (periodata-> bytesrecv> periodata-> bytessend)
{

// Post another wsasend () request.
// Since wsasend () is not gauranteed to send all of the bytes requested,
// Continue posting wsasend () calluntil all attached ed bytes are sent.

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;

// Now that there are no more bytes to send post another wsarecv () request.

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.