views:

81

answers:

2

I have to implement a game server in C which handles multiple clients and continuously exchange information with them. The client may not be sending information at all times.Should I assign a thread with non-blocking socket to them or use select() call.

Which one is better?

A: 

Both will work just as well in most cases. Note that the thread version will use blocking sockets, and the select-based uses non-blocking sockets. In the case of a server, you may feel that events for data received is a good model.

The threaded version will have the memory-overhead of allocating a stack for each thread (often the size of a page), but you can program as if you have only one client.

The evented version needs to maintain state between callbacks, which can be more work, but again, in servers it feels quite natural.

henle
A: 

select() is the way to go, that's what it's made for. If you go for the threaded non-blocking approach, you will have to implement a sleep after each tick or the thread will use all available cpu time. So, the worst case response time, if one client is sending data, is your sleep value. You could also implement one thread per socket and make it blocking, but depending on how many sockets you have, that will be much overhead.

With select() you can watch all sockets at once (no matter if they are blocking or not, btw) and only have to process those which are active.

If you are on linux an have many sockets to watch, you can take a look at epoll()

falloutboy
My server has to deal with 4 clients at the same time, so what should I use ?
sahil
the easiest way is to use select and one single thread. But, if the server has very many things to compute before sending an answer, you can think about a multi threaded solution
falloutboy
Note that on Linux, due to a bug in the kernel which they refuse to fix, you **must** set the socket to nonblocking mode even if you will be using `select`, if it's a UDP socket. The reason is that the kernel wakes up the process from `select` when it receives a packet without checking the checksum on the packet, so if the checksum was invalid, your process will wake up then block when it actually tries to read, introducing a major DoS vulnerability against your server.
R..
@sahil: I disagree, select() is probably not the easiest way, even though personally I think it's the cleanest way. When you need only 4 clients, the threaded version will consume very little memory and can take advantage of multiple CPU cores.
henle
@R: Do you have an example of when you would use blocking sockets with `select`?
henle
@henle: Programs are written with `select` so that a single thread *never* has to block on network I/O. Using blocking sockets works counter to that goal and should be considered a programming mistake (probably a common one though).
Karmastan
@Karmastan: You could use it to wait for the receive buffer to fill with SOMETHING, and then read blockingly. It just seems very contrived, so I didn't understand R's point.
henle
@henle: programming multithreaded isn't a no-brainer either, you have to deal with mutexes, raceconditions and stuff.
falloutboy
@henle: R's point is that if select() returns and notes that there is data available on a certain file, there may or may not actually be data there. If you forgot to make the next recv() non-blocking, then your one main event loop just might block waiting for data that never arrives.
Karmastan
Yes, and there may be less data than you try to read, and that will block too. I don't understand why, as R suggests, this is not expected behaviour.
henle