Jump to content
  • Advertisement

Archived

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

Krylloan

Multithreaded Server / Client structure.

This topic is 5265 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

Is this a decent multi-threading server-client setup? (Very pseudo-code. "lis", "acc" and "cli" are socket descriptors. "acc" can be multiple descriptors.) "run" is shorthand for create new thread starting at this function. ----------SERVER----------- SERVER_THREAD: (Main Server Program Thread) ------------- lis = socket() bind(lis) run LISTEN_THREAD --continue with game-- close(all acc''s) close(lis) LISTEN_THREAD: (A Secondary Server Thread) ------------- listen(lis) loop(if not closing) { acc = accept() run ACCEPT_THREAD } ACCEPT_THREAD: (Multiple Server Threads) ------------- recv(acc) ----------CLIENT----------- CLIENT_THREAD: (Main Client Thread) ------------- cli = socket() connect(cli) run CONNECT_THREAD --continue with game-- close(cli) CONNECT_THREAD: (A Secondary Client Thread) -------------- recv(cli) Is this a good network layout for a game? Is close() the correct way to abort the recv() and accept() calls? Thanks for all comments.

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Depending on the Operating System, the socket descriptors might be reference counted.

This means that when the main-thread closes a socket, the count goes down to 1 (the client-thread or accept-thread is still referencing the socket), but not 0. This means that the close() call in the main-thread becomes a no-op.

Share this post


Link to post
Share on other sites
So how should I gracefully close the accept() and recv() calls?

There is no guarantee that the application will close when the game ends, it just goes back to the menu.

Share this post


Link to post
Share on other sites
Hello Krylloan,

From the looks of it your done find in the serve side except main thread should not have to close anything.

server:
Main thread create socket bind and passes to accept thread.
accept thread that listens for connection request, when it get one it passes the returned file desc(socket) to a connection process thread, when it stop running it should close the listen socket.
connection process thread does recv/send and when its finished closes socket it was using.

In client i would have the client connection thread handle getting socket and connection not main thread.

client:
Main thread creates a connection thread telling it host and port to connect to.
connect thread creates socket, connects then if connected goes into a loop to recv/send messages.

note that if this is TCP you can only and should only call connect only until connection is made, after that do not call connect on that socket.
UDP you can call connect many times so as to change port/host.

So if server connection thread loses a connection stop the thread.
If the client connection thread loses connection just have it close the socket create a new socket and connect and then go back to processing.

Lord Bart

[edited by - lord bart on June 11, 2004 8:47:10 AM]

Share this post


Link to post
Share on other sites
> Is this a decent multi-threading server-client setup?

Tough call without more details. I don''t see anything wrong, but it all depends on what your game does and how many gamers you plan for. Having multiple service threads make sense if each client request has complex processing needs that would still be ongoing when another request arrives on the wires. Otherwise you should be thinking along a singly-threaded app line and increase the incoming buffer size instead.

Assuming you still want the network communication layer to be threaded, you can avoid having to deal with more than one socket thread on the server side by simply using ''select()'' on the accept socket (lis) along with the fully connected sockets it will create (acc{0}...acc{N}).

Beyond 200 or so client threads, your server will start to choke and unless you happen to have a multi-CPU machine, performance per user will drop significantly. This will happen sooner if the server-side game engine involves non-trivial computations such as collision detection, physics, AI, etc. or has a high simulation rate (say, one full update per 50ms).

Again, nothing wrong with the design but wondering if this design is suited to your game.

-cb

Share this post


Link to post
Share on other sites
Kuphryn:
I was planning to leave this up to the user running the server. Since the actual data throughput should only be about:
(300 Bytes / second) per Client to server
(100*NumClients / second) per Client from server
I figure a gigabit server should be able to provide for hundreds of players simultaneously, assuming the network architecture allows this. But for starters I''m only gonna be using about 10 max. I know there''s some difficulty getting over 64 connections, but I haven''t bothered to look into it yet.
I''d prefer not to set an arbitrary limit because, since computers are always improving, there will come a day when computers could easily handle more clients than has the arbitrary limit.


Lord Bart:
Ok, shifted the connect() to the client''s CONNECT_THREAD. Thanks

The problem is that the accept() and recv() threads are never going to close if they don''t recieve anything. They are on infinite wait time (And I''d like to leave it that way).

If my server decides to stop serving the game, but remain in the aplication, the accept thread needs to stop, since there is no game to connect to.

If my client wants out I could just wait for the next recv() to come, but if the client is lagging / disconnecting that may take a while, and exiting a server should be instant. So the recv() needs to be stopped from outside.

I''d prefer not to terminate an active thread manually, I''m hoping there''s a better solution.


I just looked at the "shutdown" command. Does this accomplish what I''m after. (Basically call shutdown from the SERVER_THREAD or CLIENT_THREAD on the sockets that are currently accept()ing or recv()ing.

Share this post


Link to post
Share on other sites
Hello Krylloan,

Sorry about late reply.

There are two ways you can stop your accept thread.

1) send a dummy connect with a message that means stop.
Just in your server app connect up to the port and send stop message. After accept read data and check to see if it was a stop message.

2) send a signal to the thread. not sure what OS you are using.
You should be able to send a signal to a thread. If the thread is in a blocking system call it should come out of that call into a signal handler. Now if you don''t have the socket set up to resume then after the signal handler you should be at next statement after accept. Accept should have return a -1 error. Then check if told to keep running, if not stop.

Form what I understand shutdown only sets the socket to not be able to send or recv data. So this would not stop your thread.

Of the two ways I listed above I prefer #1 the connect and send stop message. Signals can be a bit tricky when you’re dealing with multiple threads.

Lord Bart

Share this post


Link to post
Share on other sites
just a side note: too many threads are not good. if you use windows, i heard that microsoft once recommended not to use more than 2 threads per cpu. A big problem can be if you create one new thread per client because thread creation on windows is expensive.

if you are just starting programming your game, then i'd recommend you start with one single process, no threads, managing connections with select() and processing messages serial, not parallel. In my experience you can easily handle 15 to 30 clients that way. Should be enough for the beginning.

Then later you can still use a thread pool and assign each client to a thread, and then have each thread call select() on its connected clients. But you shouldn't have more than a couple of threads... depends if you use windows or linux. linux (esp. 2.6) can create a lot of threads...

hth
Chris

Share this post


Link to post
Share on other sites
Me and two of my friends have written a multiplayer game. First using multithreaded server. This was the worst thing we do. Even with one client connected to server. On server side everthing was fine but on client side everything was very bad. Network LAG was too high. Increasing thread priority wasn't good idea. LAG increased. Then we think we can use UDP and single thread in server for reciving messages. But this also wasn't good idea. But everything looks fine. We tested the game on network without many users (100Mb/s). But on slower network with many users game crashes almost allways. The reason was that UDP don't guarantee the delivery of packets in correct succesion.

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!