locked
Creating a server and client RRS feed

  • Question

  • Hey,
    I am new to network programming, if anyone can help it would be greatly appreciated.
    I am creating a multiplayer game with XNA game studio in Microsoft Visual Studio 2010 (C# code). I know it is better to ask this question here than the XNA forums. Anyway I am using TcpListener and TcpClient classes for all connections/communications (on the server and client), information is sent from the client to the server every 10 miliseconds (the client asks for specific information, for example: what players are connected and where are they). Whenever information is about to be sent a new background thread is created (for it to do its own thing - using threads also mean if the client has high latency it wont lag the program, which is the reason why i used threads for all connections in the first place) but the question is...

    Information between the server and client is sent so fast that the SERVER actually gets mixed up and sometimes sends integer only messages back with strings. I am very lost on what to do here, should i slow down connections to every 100 milliseconds which makes a maximum of 10 fps for gameplay which might not confuse/mix up the server or mabye use multiple NetworkStreams somehow...

    I am also confused how CPU usage of the program jumps to 50% sometimes which it should not, i think the cause of this is because of the amount of messages sent or possibly the amount of threads being created. I hope I am not asking to much and that also you understood what i am saying here lol... If not say so, I will try to explain it better.

    Thanks
    Xanather!

    Take a look at my site: http://www.xanather.com

    • Moved by Leo Liu - MSFT Wednesday, July 6, 2011 3:03 AM Off-Topic (From:Visual C# General)
    Thursday, June 30, 2011 12:07 PM

Answers

  • Having a client ask the server for information is not going to work.  I'm assuming you've played multiplayer games before.  Do you understand what a ping is?

    On your developmemt machine you are in a zero ping environment because your client and your server are on the same machine.

    In the real world, a player in California talking to a server in New York is going to take 50 to 200 milliseconds to get a response.  This means that when a client initiates a request for data, it will take at least 50ms for the server to receive the request and another 50 to receive a response.  If the client is issuing requests every 10ms it's going to issue 9 or 10 requests before it gets its first response.

    Very bad.

    In a multiplayer game, the client opens a TCP connection to the server and the server streams that information to all its clients without the client asking for that information.  Likewise, the client communicates to the server when the player does something so that the server can register the action and then broadcast the fact that a player did something to all connected clients.

    Also, you will run out of memory almost instantly if you create a new thread for each request/response.  Creating a thread is not free.  The system needs to allocate a stack per thread and I believe by default the stack size is in the megabyte range per thread.

    Each client should have two threads dedicated to networking - one for listening for updates from the server and one for transmitting its updates to the server.  Likewise, the server should have no more than 2 threads per client, although 1 might make more sense.  The server needs a dedicated thread for each client that is free to block while it waits for data from the client, but it doesn't necessarily need a dedicated thread for each client for transmitting since presumably the server will broadcast to all clients simultaneously.

    This is not easy stuff.

    Good luck,

    Evan

    • Marked as answer by Xanather Saturday, July 9, 2011 8:26 AM
    Thursday, June 30, 2011 1:23 PM

All replies

  • Can you share your Send and Receive code (stripped down version if there is a lot of code)

    When you send a message from either of the endpoints, the receiver may not necessarily receive the message in the exact same format.

    E.g. if you send two strings

    "Test String One"

    "Test String Two"  as two different send operations, you may recieve them as:

    "Tes"

    "t String O"

    "neTest String Tw"

    "o"

    This is only an example, and it is not necessary that this may happen in the same format but similar splits may occur.

    Which means that you will need to set a start and end delimiter to your messages and manually check for the start and end.

    If you are already doing this then it may be some other problem and pasting your code here would be helpful

    You would probably get better answers if this is posted under the network class library forum : http://social.msdn.microsoft.com/Forums/en-US/ncl/threads


    Please mark this as answer or vote as helpful if it solved your problem

    Thursday, June 30, 2011 12:40 PM
  • Having a client ask the server for information is not going to work.  I'm assuming you've played multiplayer games before.  Do you understand what a ping is?

    On your developmemt machine you are in a zero ping environment because your client and your server are on the same machine.

    In the real world, a player in California talking to a server in New York is going to take 50 to 200 milliseconds to get a response.  This means that when a client initiates a request for data, it will take at least 50ms for the server to receive the request and another 50 to receive a response.  If the client is issuing requests every 10ms it's going to issue 9 or 10 requests before it gets its first response.

    Very bad.

    In a multiplayer game, the client opens a TCP connection to the server and the server streams that information to all its clients without the client asking for that information.  Likewise, the client communicates to the server when the player does something so that the server can register the action and then broadcast the fact that a player did something to all connected clients.

    Also, you will run out of memory almost instantly if you create a new thread for each request/response.  Creating a thread is not free.  The system needs to allocate a stack per thread and I believe by default the stack size is in the megabyte range per thread.

    Each client should have two threads dedicated to networking - one for listening for updates from the server and one for transmitting its updates to the server.  Likewise, the server should have no more than 2 threads per client, although 1 might make more sense.  The server needs a dedicated thread for each client that is free to block while it waits for data from the client, but it doesn't necessarily need a dedicated thread for each client for transmitting since presumably the server will broadcast to all clients simultaneously.

    This is not easy stuff.

    Good luck,

    Evan

    • Marked as answer by Xanather Saturday, July 9, 2011 8:26 AM
    Thursday, June 30, 2011 1:23 PM
  • I would recommend to use TCP Socket class, with TCPListener and TCPClient:

    Check here for more info.


    Mitja
    Thursday, June 30, 2011 2:49 PM
  • I understand what you are saying, I think I need to remake most of my code.

    I have only coded it so far so that the server does not send information, it only sends info when the client asks for it (which your explanation made me find out is very bad.)

    Your saying is I should use the same technique I use for the server for the client too (as a listener)? So the server can actually send data freely instead of the client spamming for information.

    Thank you
    Xanather
    Take a look at my site: http://www.xanather.com
    Friday, July 1, 2011 9:23 AM
  • I have thought of ways on how to do this, using the multi-threaded server when a client connects it creates one thread for where the server can listen for data from the client, also when this client connects its NetworkStream is saved to a list (and is deleted from the list once they disconnect/drop connection from a exception) and so when I want to send data to call the clients I use the "for" statement sending the data to all the streams in the list.

    So...
    --For the server--
    there is 1 thread for the server (to accept connections and send them to other listener threads whilst saving the networkstream in the list)
    there is 1 thread "per connection" (the listener thread)
    and
    there is only 1 thread for sending data to all the networkstreams that are saved in the networkstream list.
    If there are 10 clients there would be 12 threads running on the server...
    --For the client--
    1 thread for reading data (listener)
    1 thread for sending data

    Is this ideal? I hope you understand what I am saying.

    Thank you for leading me the right way.
    Xanather (I was aware of the 0 latency)


    Take a look at my site: http://www.xanather.com
    Friday, July 1, 2011 3:55 PM
  • Hi Xanather,

    does our friends' suggestions make sense to you?
    If so please mark useful replies as answers.
    Or please post in the Windows Phone & Xbox 360 Development Category for specialized support. Then I will move your thread into the Off-Topic Forum shortly. Thanks for your understanding.
    Leo Liu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, July 4, 2011 6:05 AM
  • Xanather,

    You know that to overcome all kind of security and other problems in past is chosen to do your kind of solutions with WCF 

    You do it still in the commodore 64 way.

    Have a look at WCF and its tools.

    http://msdn.microsoft.com/en-us/netframework/aa663324.aspx

     


    Success
    Cor
    Monday, July 4, 2011 6:44 AM