How to Use SOCKET model overlap I/O (Part 2)

Source: Internet
Author: User

4.Steps for implementing overlapping models

After so much preparation and so much ink, we can start coding. As a matter of fact, it may take a little effort to understand the internal principle of the overlapping structure, but it is really not difficult to learn how to use it, the only thing that needs to be clarified is how to know which overlapping operation is completed after we receive event notifications when we interact with a large number of clients, then you can know which socket to process and which buffer zone to retrieve data. Everything will be OK ^_^.

Next we will work with the code to explain how to complete an overlap model step by step.

Step 1]Define Variables............

# Define data_bufsize 4096 // size of the receiving buffer
Socket listensocket, // listener socket
Acceptsocket; // socket for communication with the client
Wsaoverlapped acceptoverlapped; // overlapping structure
WSAEVENT  EventArray[WSA_MAXIMUM_WAIT_EVENTS];  
// Event handle array used to notify the completion of overlapping operations
WSABUF     DataBuf[DATA_BUFSIZE] ;      
DWORD dweventtotal = 0, // total number of events in the program
Dwrecvbytes = 0, // The length of the received character
Flags = 0; // wsarecv Parameter
 

 

[Step 2] Create a socket and start listening for connection requests on the specified port

It is no different from other socket initialization methods. You can simply copy them directly, and there is no extra effort here. It should be noted that, in order to be clear, I have removed the error handling and should not normally do this, although the error rate here is relatively small.

WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
 
Listensocket = socket (af_inet, sock_stream, ipproto_tcp); // create a TCP socket
 
Sockaddr_in serveraddr; // allocate and bind the port and protocol family
ServerAddr.sin_family=AF_INET;                                
ServerAddr.sin_addr.S_un.S_addr  =htonl(INADDR_ANY);          
ServerAddr.sin_port=htons(11111);
 
BIND (listensocket, (lpsockaddr) & serveraddr, sizeof (serveraddr); // bind a socket
 
Listen (listensocket, 5); // start listening

 

Step 3: accept an inbound connection request

An accept is complete. It is the same and the same ~~~~~~~~~~

As for the use of acceptex, I will talk about it in the completion port. Here we will not instill so much, so we will not digest it. ^_^

 AcceptSocket = accept (ListenSocket, NULL,NULL) ; 

Of course, I am lazy here. If you want to obtain information that is connected to the client (often asked on the Forum), do not use NULL for the last two parameters of accept.

Sockaddr_in clientaddr; // defines the address structure of a client as a parameter.
int addr_length=sizeof(ClientAddr);
AcceptSocket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length);
// You can easily obtain the information of the connected client.
LPCTSTR lpIP =  inet_ntoa(ClientAddr.sin_addr);      // IP
UINT nPort = ClientAddr.sin_port;                      // Port

 

Step 4: Create and initialize overlapping structures

Create a new wsaoverlapped overlapping structure for the connected socket, and pick out an idle object handle "Bound" from the event handle array for this overlapping structure as mentioned earlier.

// Create an event
// Dweventtotal can be used as the index of the event array for the moment.
EventArray[dwEventTotal] = WSACreateEvent();      
 
Zeromemory (& acceptoverlapped, sizeof (wsaoverlapped); // set it to zero
Acceptoverlapped. hevent = eventarray [dweventtotal]; // associate events
 
char buffer[DATA_BUFSIZE];
ZeroMemory(buffer, DATA_BUFSIZE);
DataBuf.len = DATA_BUFSIZE;
Databuf. Buf = buffer; // initialize a wsabuf Structure
Dweventtotal ++; // Add one to the total

 

Step 5: UseWsaoverlappedThe structure is a parameter, which is delivered on the socketWsarecvRequest

After all the variables have been initialized, we can start the socket operation, and then let the wsaoverlapped structure manage the I/O Request for us. We only need to wait for the event to trigger.

if(WSARecv(AcceptSocket ,&DataBuf,1,&dwRecvBytes,&Flags,
                                        & AcceptOverlapped, NULL) == SOCKET_ERROR)
{ 
// It is normal to return wsa_io_pending, indicating that the IO operation is in progress and cannot be completed immediately
// If it is not a wsa_io_pending error, it will be very difficult ~~~~~~!!!
      if(WSAGetLastError() != WSA_IO_PENDING)    
      {
// You can only close Daji.
                         closesocket(AcceptSocket);
                         WSACloseEvent(EventArray[dwEventTotal]);
         }
}

 

Step 6] UseWsawaitformultipleeventsThe function waits for the result returned by the overlapped operation.

We have previously assigned an event object handle to the overlapping structure associated with wsarecv. Therefore, we need to wait for the event object to be triggered in concert with it, in addition, you need to determine which event in the event array is triggered Based on the return value of the wsawaitformultipleevents function. For the usage and return value of this function, refer to the previous basic knowledge section.

DWORD dwIndex;
// Wait until the overlapping I/O call ends
// Because we bind the event with overlapped, we will receive an event notification after the overlap operation is completed.
dwIndex = WSAWaitForMultipleEvents(dwEventTotal, 
EventArray ,FALSE ,WSA_INFINITE,FALSE);
// Note that the returned index is not the index of the event in the array, but is subtracted from wsa_wait_event_0.
dwIndex = dwIndex – WSA_WAIT_EVENT_0;

 

Step 7: UseWsareseteventFunction reset the currently used event object

Once an event has been triggered, it has no use value for us, so we need to reset it for the next use. It is very simple, just one step, and even the return value does not need to be considered.

WSAResetEvent(EventArray[dwIndex]);

 

Step 8: UseWsagetoverlappedresultReturns the status of the function to obtain overlapping calls.

This is what we are most concerned about. What is the result of this overlapping operation that requires a great deal of shipping? In fact, for this model, the only thing that needs to be checked is whether the socket connection of the other party has been closed.

DWORD dwBytesTransferred;
WSAGetOverlappedResult( AcceptSocket, AcceptOverlapped ,
&dwBytesTransferred, FALSE, &Flags);
// First, check whether the communication peer has closed the connection.
// If = 0, the connection is established, and the socket is closed.
if(dwBytesTransferred == 0)
{
         closesocket(AcceptSocket);
Wsacloseevent (eventarray [dwindex]); // close the event
         return;
}

 

Step 9: "enjoy" the received data

If the program is executed here, it means everything is normal. The wsabuf structure contains data from our wsarecv and it is time to enjoy the results! Have a cup of tea and have a rest ~~~ Pai_^

Databuf. Buf is a char * string pointer. Let me leave it alone.

 

Step 10: continue delivery on the socket, as in step 5WsarecvRequest, repeated steps6 ~ 9

In this way, we can finally receive data from the client, but in retrospect ~~~~~, Isn't it possible to receive data only once, and then the program will not be over ?....... -_-B. Therefore, we have to repeat Step 4 and Step 5 to deliver another wsarecv request on this socket and make the entire process loop, are u clear ??

You can refer to my code, so I will not write it here, because you must be more smart than me. After understanding the key, you can think a little more flexibly.

 

 

5.Considerations for multiple clients

After completing the above loop, the overlap model has basically been set up to 80%. Why not 100%? Because, in retrospect ~~~~~~~, Isn't it possible to connect only one client ?? Yes, if you only process one client, the overlap model has no advantage at all. We just want to use the overlap model to process multiple clients.

So we have to make some changes to the structure.

1.First, a socket array must be used to communicate with each socket.

Secondly, because each socket operation in the overlap model needs to be "Bound" with an overlapping structure, a wsaoverlapped structure should be used for each socket operation, but this is not strict, because if each socket has only one operation at the same time, such as wsarecv, a socket can correspond to a wsaoverlapped structure, but if a socket has two operations: wsarecv and wsasend, therefore, a socket must correspond to two wsaoverlapped structures, so how many socket operations will have multiple wsaoverlapped structures.

Then, a wsaevent event is required for each wsaoverlapped structure. Therefore, the number of socket operations should be the number of wsaoverlapped structures, the number of wsaoverlapped structures should be as many as the number of wsaevent events. It is best to associate socket-wsaoverlapped-wsaevent so that it will not be messy until the critical moment is reached :)

 

2.It has to be divided into two threads:

A connection used for loop listening, receiving requests, and then sending the first wsarecv request to the socket with a wsaoverlapped structure, and then entering the second thread waiting for the Operation to complete.

The second thread is used to keep the wsaevent array wsawaitformultipleevents, wait for the completion of any overlapping operation, and then process it according to the returned index value. After the processing is complete, it will continue to deliver another wsarecv request.

Note that we set the parameter of the wsawaitformultipleevents function to WSA _

Infinite, but it is not OK when there are multiple clients. You need to set a timeout time. If you wait for the timeout and then re-run wsawaitformultipleevents, because the wsawaitformultipleevents function is blocked when it is not triggered, we can imagine that if the listening thread accesses a new connection, it will naturally add an event for the connection, however, wsawaitformultipleevents is still blocked and will not process the event of the new connection. I do not know whether it means that there is no ...... -_-B may not be available here, and you will understand it when coding it.

 

For other things you may not understand, refer to my code. There are also detailed comments in the Code. Enjoy ~~~

However, it is a pity that the code of MFC is used to take care of most people, and the code is a little messy.

 

6.Known issues

This known issue refers to the known issue in my code, but not the known issue of overlapping structures :)

This sample code has been written for a long time. During the last test in the past two days, we found that there were actually two bugs, but not every time, 5555, recently, I have no energy to change these bugs. If you are interested in fixing these two bugs, it will benefit you. This article is almost aborted, I have never experienced any bugs in code that I almost forgot to modify. I wrote them here to remind you that the code is just a reference, in addition, I think the text is more precious than the code ^ _ ^, because there are still a lot of overlapping model code online. The two bugs are as follows:

1. Exceptions may occur when multiple clients exit consecutively;

2. Sometimes the receiving buffer of multiple clients will overlap, that is to say, the data sent by Client A will be followed by the data sent by client B last time ..... -_-B

Improved Algorithms: in fact, there are still many improvements to the algorithms in the Code. Limin mentioned several very good improved algorithms to me, such as how to find idle sockets in the socket array for communication, but I didn't add it to this Code, because the code of the overlapping model is complicated. I am afraid that adding these things will bring difficulties for beginners. However, you are welcome to discuss with me the algorithm for improving overlapping models and the problems in my code! Pai_^

 

Let's just say so much. I hope you can use this article to become proficient in overlapping I/O models. Pai_^

We look forward to the next article in this series, "How to teach you how to use socket models by hand"

------ Finished in dlut | dip

------ 2004-09-22

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.