Self-study Winsocket IO Methods

zhaozj2021-02-16  26

Self-study Winsocket I / O Methods

1. First, you need to know what is "socket model", what is "socket I / o models"? Socket Modes: DETERMINESHOW WINSOCK FUNCKET.SOCKET I / O Models: Describes How an Application Manages and Processes I / O On A Socket.2. So What kind of "Socket Modes" have provided programmers for programmers? A.Blocking Mode (non-blocking) 3. Detailed explanation Blocking and non-blocking. Our most commonly used Send and RECV two functions ... For example, you call the send function to send a certain Byte, in the system's internal Send works actually to transfer data transfer (COPY) to TCP / The Output buffer of the IP protocol stack, it does not mean that the data has been successfully sent. If the TCP / IP protocol stack does not have enough available buffers to save the data you Copy ... This time is reflected in this time The difference between blocking and non-blocking: The Socket Send function of the blocking mode will not return until the system buffer has enough space to return the data you want to send, and the Socket for blocking will be immediately Returns WSAEWOULDDBLOCK to tell the caller: "Send operation is blocked !!! You want to handle it ..." For the RECV function, the same truth, the internal work mechanism of this function is actually waiting for the TCP / IP protocol stack The area notifies it: Hey, your data is coming. For the Socket of the blocking mode, if the TCP / IP protocol stack receives the buffer that does not know a result to it, it has not returned: the system resource .... Socket this function will return immediately, then tell you: WSaewouldDblock.3. For blocking mode, don't I get it? Don't get it, and don't use me to judge the basic receipt / what Time to complete, more people? Yes, this prawn said the way the way the way is as follows: We divide the application into a Working Thread, two threads are synchronized Object (Synchronization Object, can be Event, Mutex ...) to share a data buffer, read thread (Read ING THREAD) is responsible for reading data from the network and placing it in a shared buffer, triggering an event, notifying / waking up working thread, notifying / waking up a working thread in an appropriate timing (such as receiving the data required by the reading thread). ), the following is a simple code of the character to achieve: CRITICAL_SECTION g_data; HANDLE g_hEvent; TCHAR g_szBuffer [MAX_BUFFER_SIZE]; int g_nBytes; void ReadThread (void) {int nTotle = nRead = nLeft = nBytes = 0; while (done) {nTotal! = 0; NLEFT = NUM_BYTES_REFT = NUM_BYTES_REQUIRED; / / To read how much bytes while (NTOTAL! = Num_Byte_Required) {// Because of thread and global variables, you need to use critical segments EntercriticalSECTION (& g_data); NREAD = Recv (SOCK, & (g_szbuffer [max_buffer_size] - nbytes), NLEFT); if (-1 ==

NREAD) {Printf ("socket% d error./n", wsagetlaserror ()); exitthread ();} ntotal = nread; nLEFT - = NREAD; NBYTES = NREAD; LeaveCriticalSelection (& g_data);} // From network WorkThread start notification SetEvent (g_hEvent) after completing reception of the specified (NUM_BYTES_REQUIRED) Bytes;}} void WorkThread (void) {WaitForSingleObject (g_hEvent); EnterCriticalSection (& g_data); // main processing ... DoSomeWorkOnData (g_szBuffer); g_nBytes - = Num_byte_required; LeavecriticalSelection;} This way is that the application is difficult to communicate very difficult to connect through multiple Socket communication. Of course, let's come back to each connected socket to open a Reading Thread. And Workthread, but this will bring great overhead, and the scalability is very poor. Imagine that if you build a server with such a model to open at least two threads ... Day .. If the business burden is large / How to do a lot of Socket ?? So don't think more ... This way is very uncomfortable to do server-side. (Note: The server I said refers to the S-terminal logic in C / S).

Interpret the most complex IOCP model in IO from the perspective of writing code

One of the following paragraphs is an example in Microsoft Win32 SDK. This is an echo server program: //// This will not be said, in order to use the header file that must be included in Winsock2 ... // # include # Include #DEfine port 5150 // This server selection 5150 port #define data_bufsize 8192 // Defined buffer to 8K is a comparison of Microsoft recommended size /// This structure It is very important, please see clearly, don't confuse when you use it later, you should pay special attention: Take Overlapped is the most reasonable, you should be guilty is // If you have: // per_io_operation_data periodata; // & periodata -> Overlapped and & PERIODATA are the same / equivalent /// point to the same memory area .// typedef struct {Overlapped overlapped; wsabuf data; char buffer [data_bufsize]; dword Bytessend; // The following two parameters are used To record the DWORD BYTESRECV of the sent and received by each Connected Socket;} per_io_operation_data, * LPPER_IO_OPERATION_DATA; / / Don't confuse this structure and the structure above, the name is very like ... In fact it is in this program equivalent sockettypedef struct terminal connected to the Client and {SOCKET Socket;} PER_HANDLE_DATA, * LPPER_HANDLE_DATA; DWORD WINAPI ServerWorkerThread (LPVOID CompletionPortID); void main (void) {SOCKADDR_IN InternetAddr; //// listen and a server program is a Accept socket The old routine ... // socket listen; socket accept; /////////////////////////////////////wwle completion; system_info systeminfo; //// see clear Chu, this is a pointer ... Not afraid of you jokes, we really have a clear and pointer-related person, such as the following code: // I wrote a DLL, there is such a function: // Bool getPlayingPosition (DWORD * dWPOS); // The result is like this when the prawn is called .... // DWORD * P; // getPlayingPOStion (P); // It is called cool ... I ... - (// Of course, it is not good definition that it is not clear the pointer, maybe people will not write the program .. is right ../lpper_handle_data perhandata; lpper_io_operation_data periodata; int i; dword recbytes; dword flags; DWORD THREADID; WSADATA WSADATA; DWORD RET; // Like Coinitialize (), starting Winsock 2.2 service ... if ((RET = WSAStartup (0x0202, & WSADATA))! = 0) {Printf ("WsaStartup Failed with Error% D / N ", RET; RETURN;} // Createiocompletionport has two different purposes: 1. Create a completed port; 2. Putting the created completion port and a socket / binding. This sentence is its first use: Create a completed port IF ((CompletionPort = CreateiocompletionPort (Invalid_Handle_Value, NULL, 0, 0)) =

= NULL) {Printf ("CreateiocompletionPort Failed with Error:% D / N", getLastError ()); Return;} //// The following code is said to be: several CPUs on the machine running according to the server 2 * CPU number of thread.// This involves how many problems should be created by completing the port working thread, in the early stage (MSDN 2000) Microsoft said // is Workthreadnums = 2 * CPU 2, the current MSDN 2003 is Workthreadnums = 2 * CPU; // GetSystemInfo; for (i = 0; i

} /// Receive a connection to New Socket and under the next reception / processing of the Socket connected to the SOCKET // Why don't you use new? I think it is because the memory management function provided by Windows, this If the memory is large, there is no abnormality in the case of lack of memory, how is it that the memory allocation failed ... // if ((Perhandata = (lpper_handle_data) GlobalLococ (GPTR, SIZEOF (Per_handle_data))) == NULL) {Printf ("GlobalAlloc () Failed with Error% D / N", getLastError ()); Return;} // Associate The Accept Socket with the Original Completion Port.Printf ("Socket Number % D connection / n ", accept; perhandata-> socket = accept; //// The Accept Socket and IO complete the port association / binding / binding, and passing the Accept Socket to the IOCP mechanism. // When calling getQueuedCompletionStatus You can get this value. Return;} // The following structure will also be passed to the working thread, how to pass? Note the red part of the following red ((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-> Database; periodata-> databuf.buf = periodata-> buffer; flags = 0; //// In Accept Socket IO request: wsarecv () to stimulate the IOCP working mechanism ../ Note the fifth parameters of WSARECV, that is, I tell WSAarecv at this time, not only // periodata-> Overlapped address is also the address of Periodata. ..//IF (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;

}}}} //// worker // 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) {//// This function explains that the whole mechanism will also understand ... // First, we should see that CompletionPort should have no problem, which is passed from the main thread of the creation thread. // Bytestransferred indicates this IO How many bytes ... // perhandaTA is time to Createiocompletionport, the MSDN is called completionKey.//, please pay attention to this parameter, the explanation of MSDN is as follows: // "Pointer to a variable That Receives The Address of ADDRESS OF The overlapped structure That Was // Specified WHEN The Completed I / O Operation WAS Started. "Actually, the LPoverLapped is the overlapped address of the overlapped ... // This is understood: reputation overlapped by threads pass over a structure pointer ..: -) // if (GetQueuedCompletionStatus (CompletionPort, & BytesTransferred, (LPDWORD) & PerHandleData, (LPOVERLAPPED *) & PerIoData, INFINITE) == 0) {printf ( "GetQueuedCompletionStatus Failed with error% D / N ", getLastError ()); return 0;} ///first check to see if an erro r has occured on the socket and if so // then close the socket and cleanup the SOCKET_INFORMATION structure // associated with the socket.//if (BytesTransferred == 0) {printf ( "Closing socket% d / n", PerHandleData- > Socket); if (CloseData-> Socket) == SOCKET_ERROR) {Printf ("CloseSocket () failed with error% d / n", wsagetlasterror ()); return 0;} GlobalFree (Perhandata); globalfree ); continue;.} //// Check to see if the BytesRECV field equals zero If this is so, then // this means a WSARecv call just completed so update the BytesRECV field // with the BytesTransferred value from the completed WSARecv ( Call.//IF (periodata-> bytesRecv ==

转载请注明原文地址:https://www.9cbs.com/read-26301.html

New Post(0)