IOCP, kqueue, epoll ... How important is it?

  

Designing the mmo server, I've heard a lot of clichés about how inefficient select is when dealing with a lot of connections. We should switch to iocp (windows), kqueue (freebsd), or epoll (linux). Indeed, selecting a large number of connections to read and write, select is inefficient. Because the kernel has to poll the set of socket numbers passed in by select every time, then in Shanghai, in the case of Chen Yu, this is called the devil's strategy. Asked over and over again “ Devils into the village? & rdquo;, & ldquo; Devils into the village? & rdquo;... A lot of cpu time is spent. (Moreover, on Windows, there is a sinister 64 limit.)

Using kqueue, these become some people to go to the post, the devils can come to get notifications, the efficiency is naturally high a lot of. But recently I was rethinking. Do you really need to build a server based on these?

One of the ideas that just formed is this:

We distribute the processing of external connections and processing game logic to two servers for processing, for the sake of easy description later, temporarily not very rigorous The former is called a connection server, and the latter is called a logical server.

The connection server can do very simple things, just put together the data on multiple connections. Assuming that the total number of simultaneous connections does not exceed 65,536, we only need to add a two-byte header to the data packet on each connection. This connection server is sufficient to communicate with the logical server through a single connection.

There is a connection server that handles data in the most efficient way. Its logic is simple and the amount of code is very small. The logical server has only one external connection, no matter how it is handled, it will not be slow.

Further, we can extend this method. Suppose our logic processes logic at a frequency of 10 Hz. We let the connection server send the aggregated data periodically with a 10Hz pulse, and send a length message first and then send the data packet. Even if one pulse has no external data, it is strictly guaranteed to send at least one 0 length information. In addition, the connection server also needs to control the total data flow of each pulse, so as not to send data more than the capacity of the logical server processing.

So, the logical server can even call recv to block the data, even select is saved. As to whether the data is really blocked by the receiver, it is guaranteed by the logic of the connection server.

When it comes to blocking reception, when I talked to a colleague, he was seriously worried about the reliability of this. He didn't want to accidentally put the logical server on a system call. He cited many possible accidents, but I personally don't worry too much, and I don't want to explain more here. Of course, I designed this, mainly not to save a select call, but to facilitate debugging. (Of course, if it turns out that this is not feasible, it is easy to modify the scheme.)

Because blocking reception can guarantee the strict timing of the logical server, when we record the communication in the two servers, we can use these later. The process of completely recreating the game logic, no matter how debugging and running, can ensure that the behavior of the logical server can be completely reproduced. That is, known packets are accepted every 0.1s and then processed.

In doing so, the logic server's need for the amount of code in the network layer is greatly reduced, and the logic can be constructed more concentrically.

Copyright © Windows knowledge All Rights Reserved