-
Notifications
You must be signed in to change notification settings - Fork 675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Undersanding enet_host_service #248
Comments
There's a lot of questions but I'll only chime in on this one. If you call Hence, using a timeout of 0ms is only recommended when you have something else limiting the frequency at which this function is called (for example calling it only once per frame in a game loop, as suggested by the docs). |
All good and valid questions, I will let Lee chime in and try to answer as best as I can meanwhile. The way In old BSD sockets world, when you want to send data, you push them out using When you want to Assuming your game uses just one thread, which is what was common in the past, you see that you can block and freeze randomly. Thus Typically Ideally you call How do you know first? you use How do you know second? Well when you Now to your questions:
Specifying
Does not matter at all. You need to call
There will always be that loop where you call outer
Sooner or later you will end up with multiple threads. Since enet is single threaded and does not use any locking mechanism anywhere, you will have to make sure to have one thread to invoke all enet calls. Calling with 0 timeout and just looping will consume 100% CPU, so that is not wise. It's better to call Ideally you spawn another thread where you can do
The code tries to do its best to work in single threaded environment where you have several milliseconds per frame and you need to receive, send, handle retransmits, ACKS, etc... and the logic wants to make sure that you have predictable deadlines. So in 60fps environment you have 16ms per frame, so you give enet 5ms and it will try to make sure that you still have 10ms for other computations. But from the performance perspective it's better to put enet aside to another thread and not block the rendering thread at all. Which can be quite challenging. |
I appreciate everyone's input on this, it's definitely helping me get this. I thought I'd ask a few more which relate to more concrete code examples. Suppose we have a client which sends out packets at a rate of 20 times per second (20Hz = 0.05 seconds = 50ms). Then we have the following loop on our server. while (true) {
while (enet_host_service(..., x) > 0) {
...
}
} where If the above paragraph holds true, then what is the point of setting the variable int iterations_without_data_within_x_milliseconds = 0;
while (true) {
while (enet_host_service(..., x) > 0) {
iterations_without_data_within_x_milliseconds = 0;
...
}
iterations_without_data_within_x_milliseconds += 1;
if (iterations_without_data_within_x_milliseconds >= 5) {
... do something specific because there is no network activity for a while ...
}
} Also based on @bjorn's comment it seems like a loop of the form while (true) {
while (enet_host_service(..., x) > 0) {
}
} has the property that as |
While experimentation can't hurt, I think it just means you should keep |
I have a question relating to a client server setup that relates to
void handle_incoming_data() {
...
// Event loop
while (true) {
ENetEvent event;
// Check for events with a 100ms timeout
while (enet_host_service(server, &event, 100) > 0) { // LINE X
switch (event.type) {
case ENetEventType::ENET_EVENT_TYPE_CONNECT:
...
case ENetEventType::ENET_EVENT_TYPE_RECEIVE:
...
case ENetEventType::ENET_EVENT_TYPE_DISCONNECT:
...
default:
break;
}
}
}
...
}
void start_outgoing_data_loop() {
while (true) {
std::this_thread::sleep_until(...); // the loop runs at some fixed rate
unsigned int binary_input_snapshot = this->input_snapshot_to_binary();
printf("%d\n", binary_input_snapshot);
ENetPacket *packet =
enet_packet_create(&binary_input_snapshot, sizeof(binary_input_snapshot), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(server_connection, 0, packet);
enet_host_service(client, &event, 0); // LINE Y
}
} Now suppose that these two loops are run in their own separate threads (thread A runs the loop in The reason why the loop in Suppose that in thread B the line Also with this setup the two threads may call In general is this an ok approach to managing an "incoming" and "outgoing" thread with enet? If not can anyone share how they do this. Thanks! |
Yes, this causes race conditions. See #102 (comment) and the first question in the FAQ. |
Hey there, I've been trying to get a hang of enet, and mainly trying to understand
enet_host_service
, I've read this about it:This is also mentioned:
For context I'm working on a multiplayer game with a physics engine following a client-server architecture. The client sends out keyboard and mouse updates at a fixed rate. The server has a thread for the network and a thread for the physics loop.
Before I jump into coding the server I wanted to study some existing code which was said to be enet server code:
server.cpp
Questions
enet_host_service
is called on the server be the same rate at which it is called on the client side? What about if there are n <= 16 clients? Do I have to take this into consideration at all?enet_host_service
is encased in an outer while loop which runs constantly, this is so that if nothing happens within 100ms the program still continues to try polling again instead of exiting immediately. Is this what most people do? (havewhile enet_host_service(...)
encased in some other while loop?)enet_host_service
with a timeout of 0 in each iteration of your game loop, is this because if we put a call toenet_host_service
with a non-zero timeout in each iteration of our game loop then it would cause our game loop to run slower because this is a blocking call? B) If we use c++ and the thread library to separate out the network loop into it's own thread then is it preferred to callenet_host_service
with a non-zero timeout? C) Are there any other considerations that need to be made if we separate the enet code into it's own thread?enet_host_service
it seems thatenet_host_service
will try to send outgoing packets and receive incoming packets within a do while loop (which I believe runs until the waiting time is up). If that's the case, then what is the point of timeout because it seems like if we had a timeout of 10ms then as it's encased in awhile (true)
thenenet_host_service
would be called 10 times more often, but still leading to the same amount of time waiting for events as the 100ms wait time would produce? B) Also along the same vein, wouldn't callingenet_host_service
with 0ms of wait-time (non-blocking) as fast as possible also give the same results (when it's in thewhile (true)
loop)?enet_host_service
with a greater timeout (which means thatenet_host_service
is being called not as much as before) cause less adequate performance [based on the remark in the docs which says ' enet_host_service should be called fairly regularly for adequate performance'] B) What is the definition of 'fairly regularly'ps: if I get some good answers on how this works I'll make some pull requests to update the docs with more info about the relevant topics.
The text was updated successfully, but these errors were encountered: