four. Steps to achieve overlapping model
I have made so many preparations, and so many pens, we can finally start to encode. In fact, you will understand that you will understand that the internal principles of dialysis of the overlapping structure may be a good job, but just learn how to use it, but it is really not difficult, the only thing that needs to be cleared, it is a lot of In the case of the client interaction, we get the event notification, how to know which overlap operation is completed, then know which socket is handled, which buffer should go to get data, everything Will Be OK ^ _ ^.
Below we cooperate with the code, explain how to handle a overlapping model in step by step.
[First step] Define variables .........
#define data_bufsize 4096 // Receive buffer size
Socket Listensocket, // Listening Socket
Acceptsocket; // Sockets communicating with the client
Wsaoverlapped acceptoverlapped; // overlapping structure
WSAEVENT EVENTARRAY [WSA_MAXIMUM_WAIT_EVENTS];
// Event handle array used to notify overlapping operations
WSABUF DATABUF [DATA_BUFSIZE];
DWORD dweventtotal = 0, // Total number of events in the program
DWRECVBYTES = 0, // Received Character Length
Flags = 0; // WSARECV parameters
[Step 2] Create a socket and start listening to the connection request on the specified port
And other Socket initialization all the whole, direct movement, there is not much lips, you need to pay attention to it, I have dropped the wrong handling, usually don't like this, although the chance of error here is relatively small. .
Wsadata wsadata;
WSASTARTUP (Makeword (2, 2), & WSADATA);
Listensocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create TCP socket
SockAddr_in ServerAddr; // Assign port and protocols and bind
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)); // Binding Socket
Listen (Listensocket, 5); // Start listening
[Step 3] Accept a connection request
An accept is finished, all is the same as the same, ~~~~~~~~~~
As for the use of Acceptex, I will talk in the completion of the port, here is not so much in turn, it is not digested ^ _ ^
Acceptsocket = accept (listensocket, null, null);
Of course, here is what I lazy, if you want to get a client's information (remember to ask someone on the forum), the last two parameters of Accept do not use null, but this
SockAddr_in clientaddr; // Defines a client's address structure as a parameter int Addr_length = sizeof (clientaddr);
Acceptsocket = accept (listensocket, (sockaddr *) & clientaddr, & addr_length;
// What can we easily learn about the client.
LPCTSTR LPIP = INET_NTOA (ClientAddr.sin_ADDR); // ip
Uint nport = clientaddr.sin_port; // port
[Fourth step] Establish and initialize overlapping structure
To connect this socket, a wsaoverlapped overlapping structure is newly established, as mentioned earlier, picking out an idle object handle "binding" from the event handle array as before.
// Create an event
// DWEventTotal can temporarily act as an index of an EVENT array
EventArray [dweventtotal] = wsacreateevent ();
ZeromeMory (& Acceptoverlapped, Sizeof (Wsaoverlapped); //
Acceptoverlapped.hevent = EventArray [dweventtotal]; // Association event
Char buffer [data_bufsize];
ZeromeMory (buffer, Data_bufsize);
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer; // Initialize a WSABUF structure
DWEVENTTOAL ; // Total number plus one
[Fifth] The WSAOVERLAPPED structure is parameter, and the WSARECV request is delivered on the socket.
After each variable has initialized OK, we can start Socket operation, then let WSAOverlapped structure manage I / O requests for us, we only use the trigger of the waiting event to be OK.
IF (WSarecv (Acceptsocket, & DataBuf, 1, & Dwrecvbytes, & flags,
& Acceptoverlapped, NULL) == Socket_ERROR)
{
// Returns WSA_IO_PENDING is normal, indicating that the IO operation is in progress, and cannot be completed immediately.
// If it is not a WSA_IO_PENDING error, it is not good ~~~~~~! ! !
IF (wsagetlasterror ()! = WSA_IO_PENDING)
{
// then only turn off the big joy.
CloseSocket (ACCEPTSOCKET);
WSACloseEvent (EventArray [dweventtotal]);
}
}
[Step 6] WosawaitFormultiPleEvents function Waiting the result of overlapping operations returned
We have already assigned an event object handle, so we have to wait for the trigger and cooperation of the event object, and need to determine which event in the event array is triggered according to the return value of the WSAWAITFormultiPevents function. The usage and return values of this function refer to the basics part of the previous.
DWORD DWINDEX;
// Waiting for overlapping I / O end
// Because we bind the event and overlapped, we will receive the event to notify dwindex = WSAWAITFORMULTIPLEEVENTS (DWEventTotal,
EventArray, False, WSA_INFINITE, FALSE;
// Note that INDEX returned here is not an incident in an incorption, but it is necessary to subtract WSA_WAIT_EVENT_0
Dwindex = dwindex - WSA_WAIT_EVENT_0;
[Seventh step] Use the WSARESETEVENT function to reset the current useful event object
After the incident has been triggered, it has not used value for us, so you have to reset it to leave it next time, it is very simple, one step, even return value does not have to consider
WSARESETEVENT (EventArray [dwindex]);
[Eighth Steps] Use the WSAGETOVERLAPPEDRESULT function to get the return status of overlapping calls
This is our most concerned, what is the result of this overlap operation? In fact, for this model, the only thing to check is whether the other party's Socket connection has been closed.
DWORD DWBYTESTRANSFERRED;
WsagetoverlappedResult (Acceptsocket, Acceptoverlapped,
& DWBYTESTRANSFERRED, FALSE, & FLAGS;
// Check if the communication other party has closed the connection
// If == 0 indicates that the connection has been connected, turn off the socket.
IF (DWBYTESTRANSFERRED == 0)
{
CloseSocket (ACCEPTSOCKET);
WSACloseEvent (EventArray [dwindex]); // Close event
Return;
}
[Ninth Step] "Enjoy" received data
If the program executes here, then explain that everything is normal, the WSABUF structure has the data from our WSARECV, and finally the time to enjoy the results! Cup of tea, take a break ~~~ ^ _ ^
DataBuf.buf is a char * string pointer, listen to your handle, I don't say much.
[Chapter 10] Like the fifth step, continue to deliver WSARECV requests on the socket, repeat steps 6 ~ 9
This way, we can finally receive data from the client, but recall it, yeah ~~~~~, is this not only available, then the program is not over? ......-_- b so we have to repeat the work of the fourth steps and fifth steps, and then deliver another WSARECV request on this socket, and make the entire process loop, Are u clear? ?
Everyone can refer to my code, here is not written here, because everyone must be better than me smart, after understanding the key, slightly thinking is flexible.
Fives. Multiple client conditions
After completing the above cycle, the overlapping model has basically constructed 80%, why isn't it 100%? Because I think it carefully, it is ~~~~~~~, can I only connect one client? ? Yes, if only one client is processed, the overlapping model is not there, and we are using the overlapping model to handle multiple clients.
So we have to make some changes to the structure.
1. First of all, it is definitely a set of socket arrays, used to communicate with each Socket, respectively.
Secondly, because each Socket operation in the overlap model is to "bind" a overlapping structure, you need to match a WSAOverlapped structure for each Socket operation, but this is not strict, because if every Socket is only one operation For example, wsarecv, then a socket can correspond to a WSAOverlapped structure, but if there is WSARECV and WSasend two operations on a socket, then a socket must correspond to two WSAOVERLAPPED structures, so how many Socket operations will be WSAOVERLAPPED structure. Then, it is also a WSAEVENT event for each WSAOverlapped structure, so how many WSAEVERLAPPED structures should be said, how many WSAEVENT events should be made, and the SOCKET - WSAOVERLAPPED - The association of three WSAEVENTs, it will not be in danger of critical moments :)
2. Have to divide two threads:
A connection to loop listening ports, receive requests, and then deliver the first WSARECV request on this socket, then deliver the first WSARECV request, and then enter the second thread waiting to be completed.
The second thread is used to keep the WSAEVENT array WSAWAITFORMULTIPEEVENTS, waiting for any overlapping operation, and then processes according to the returned index value, and then continue to deliver another WSARECV request.
It is important to note that, I am setting the parameters of the WSAWAITFORMULTIPEEvents function to WSA_
Infinite, but in multiple clients, it is not OK. You need to set a timeout. If you wait for timeout, you will re-wsawaitFormultiPleevents, because the wsawaitformultipleevents function is blocked when there is no trigger, we can imagine, this If the listening line is entered into a new connection, it will naturally add an EVENT for this connection, but WSAWAITFORMULTIPEEVENTS still blocks it there will be newly connected Event. I don't know if I understand. . . . . . -_- b may not be here, you will understand when you really encode.
Others can also refer to my code, there are more detailed notes in the code, enjoy ~~~
However, it is a pity to take care of most people, use the MFC code, and the code is somewhat mess.
six. Question
This known issue is to say that the known issue in my code is not a known issue of overlapping structure :)
This sample code has been written for a long time. When these two days did the final test, they found that there were two bugs, but not every time, 5555, I recently really didn't have energy to change, if you have a friend It can be modified by these two bugs, it is really benefiting everyone. This article is dangerous. I have not experienced the bug that I have to go to the code. I have to ask for forgetting. I have written here. Let's have you. It's just a throwing brick, and I think it is more precious than the code or the text is more precious ^ _ ^, because the code online of the overlapping model is still a lot. Two bugs are like this:
1. When multiple clients are continuously exit, they sometimes appear;
2. Sometimes the receiving buffers of multiple clients will be overlap together, that is, the data sent by the A client will have the data from the b client to be last time. . . . . -_- b improvement algorithm: The algorithm in the actual code has many places that can improve, and friends will mention several very good improvement algorithms to me, such as how to find idle Socket in the socket array to communicate, But I didn't add this code, because the code of the overlap model is more miscellaneous, plus these things, I will have difficulties to introduce beginners. But very welcome and I discuss the improved algorithm for overlapping models and problems in my code! ^ _ ^
Just say so much, I hope that you can use this article to play the illegal IO model, there is no effort to spend this effort. ^ _ ^
Please look forward to this series of the next article "Hand teaches you to play the SOCKET model" completion routine "
------ Finished in dlut | DIP
--------
2004-09-22