Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Khelz

Blocking, Non-Blocking, or Async sockets for my server ?

This topic is 6028 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement
While we''re on the subject I have a question of my own

I recently wrote a simple "game" server which created two threads - one to do networking stuff and the other to control the gameplay. The two threads communicate via messages queues.

The network thread does this:
  check socket for client messages
  process messages, push anything required for gameplay onto the gameplay message queue
  check outgoing queue for gamestate updates from the gameplay queue and broadcast them to clients.

While the gameplay thread is doing this:
  check queue for messages from network thread
  update gamestate according to messages. move bots around
  if it''s time to do so, push a gamestate update onto the outgoing queue for the network thread to broadcast.

I did this because i wanted to separate the blocking network sockets from the gameplay (for aesthetic reasons and to keep the gameplay running independently of network stuff.)

The problem is that the network thread blocks on the recvfrom waiting for client updates, and so gamestate updates can''t be broadcast to the clients until the recvfrom moves on.

I thought of a few possible ways to get around this. The first one is to make the socket non-blocking, in which case I may as well just put the whole thing in a single thread.

The next one was to put the broadcast method in the gameplay thread which means I need two sockets and have network code in the gameplay thread which I was trying to avoid.

And lastly I thought I could instead create make a gameplay process as a child or subprocess of the network process and have them communicate via a pipe. That way the network process can do a select on the network socket and on the pipe.

Does anyone have any comments or other ideas? I would very much appreciate them

Share this post


Link to post
Share on other sites
Number one, what platform are you programming on?

Number two... if you have two threads, why not THREE... ? Wouldn''t that be easier and better than integrating something into your gamestate thread?

Share this post


Link to post
Share on other sites
quote:
Original post by sQuid

The problem is that the network thread blocks on the recvfrom waiting for client updates, and so gamestate updates can''t be broadcast to the clients until the recvfrom moves on.




ok, here''s my 2 cents. Depending on which platform you''re on,
you could do these things. On *nix, you can use a POSIX semaphor
or Mutex to lock your outbound queue. The calls to generate
these things create a filedescriptor handle which you can
pass to select(). Now select will interrupt if there is
data available on your outbound queue (mutex released) , because the read state on the descriptor will
be set. I''ve implemented that and I know that it works
Ok, on Win* things look different because the use of select()
isn''t encouraged and you don''t have the descriptors.
What I''ve thought about would be to use WSAWaitForMultipleEvents() function
to control your networking thread. Then, have your locking mechanism Create/Set a Event that is caught by the WSA* function.
In that case you get an interrupt as well and the outbound queue will be processed.
Does this make sense ? I haven''t tried that yet (but will shortly) but it seems to be a workable way.


Share this post


Link to post
Share on other sites
On *nix, you can use a POSIX semaphor or Mutex to lock your outbound queue. The calls to generate these things create a filedescriptor handle which you can pass to select(). Nows elect will interrupt if there is data available on your outbound queue (mutex released) , because the read state on the descriptor will be set. I''ve implemented that and I know thati t works

Thanks, thats more like 20c I am on *nix (which I should have mentioned first up) and the queues are already using mutex locks so that took me 2 minutes.

Share this post


Link to post
Share on other sites
It works on Windows, too. I tried the following :
(for those interested ;-) )
1. Create WSAEvents for the Socket and the locking object
2. Use WSAEventSelect to associate socket and event
3. use SetEvent() to manually set event when releasing the lock
4. use WSAWaitForMultipleEvents to interrupt mainloop when either event occurs.

Cheers !

Share this post


Link to post
Share on other sites
The calls to generate these things create a filedescriptor handle which you can pass to select().

You couldn''t give me a little more detail on this could you?
Thanks

Share this post


Link to post
Share on other sites
hey, I was mixing things up, sorry. On IRIX, there is a function
available called usopenpollsema() which gives you direct access to the filedescriptor. If you are using posix stuff, I would use something like a pipe. Here it goes:
1. create a pipe() and use one filedescriptor in your game thread
2. take the other filedescriptor and pass it to select via FD_SET(...);
3. If your game thread finishes updating the outbound queue, write a single byte onto the pipe, in which case the other filedescriptor will become writeable (and select() returns).

you might still want to use some synchronisation to control access to the queue

hope that helps.


Edited by - behemoth on February 14, 2002 6:54:57 AM

Share this post


Link to post
Share on other sites
Cool, that''s all working great now.

But I figure if I''m writing to a pipe I may as just forget the queue altogether and just get the game thread to write updates and the net thread to read them directly from the pipe.

A computer scientist friend of mine said there was another way to do it, if it''s interesting I''ll post it on this thread.

thanks again

Share this post


Link to post
Share on other sites
Yes, I would be interested in different methods. I think if
you are on *nix you could use some signal mechanism as well. Have the game thread send a signal to the network thread when the outbound queue gets filled and have a signal handler deal
with it. I think there might be an issue with signal backlog but
I''m not sure. Haven''t tried that one ;-)

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!