2-player game, client and server at localhost

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Michael Rybak

    #1

    2-player game, client and server at localhost

    hi, everyone.

    I'm writing a 2-players game that should support network mode. I'm now
    testing it on 1 PC since I don't have 2. I directly use sockets, and
    both client and server do computations, the only data transfered is
    user mouse/kbd input.

    It works synchronously, but somehow, when I play in client window,
    both client and server have 17 fps, while when playing in server
    window, server has 44 fps while client has 5, and due to forced
    synchronization , they both run very slowly (I wonder how come server
    says it has 44fps?).

    Does anybody have an idea how can this be? Not that users will test 2
    game intances communicating via localhost, but I need to make it work
    properly.

    --
    Best Regards,
    Michael Rybak mailto:accepted @ukr.net

  • Peter Hansen

    #2
    Re: 2-player game, client and server at localhost

    Michael Rybak wrote:[color=blue]
    > I'm writing a 2-players game that should support network mode. I'm now
    > testing it on 1 PC since I don't have 2. I directly use sockets, and
    > both client and server do computations, the only data transfered is
    > user mouse/kbd input.
    >
    > It works synchronously, but somehow, when I play in client window,
    > both client and server have 17 fps, while when playing in server
    > window, server has 44 fps while client has 5, and due to forced
    > synchronization , they both run very slowly (I wonder how come server
    > says it has 44fps?).
    >
    > Does anybody have an idea how can this be?[/color]

    I'd suggest not spending time profiling, debugging, optimizing a
    "home-brewed" implementation using sockets but switch to Twisted or Pyro
    or something like that and save yourself a lot of headaches.

    Chances are this will magically speed things up to acceptable levels, too.

    -Peter

    Comment

    • Dennis Lee Bieber

      #3
      Re: 2-player game, client and server at localhost

      On Sat, 30 Jul 2005 19:36:52 +0300, Michael Rybak <accepted@ukr.n et>
      declaimed the following in comp.lang.pytho n:

      [color=blue]
      > It works synchronously, but somehow, when I play in client window,
      > both client and server have 17 fps, while when playing in server
      > window, server has 44 fps while client has 5, and due to forced
      > synchronization , they both run very slowly (I wonder how come server
      > says it has 44fps?).
      >[/color]
      Well, for a 2 player game of this sort, I'd think there should
      be one server and TWO clients... It sounds more like you have a
      master-slave arrangement with the slave forced to synchronize to the
      master.

      If you are running on Windows, the program with the input focus
      is probably running at a higher priority... So the "server", when having
      input focus, gets to compute lots of stuff while the client gets less
      CPU time... and if the client then (whenever it does a frame say) does a
      transaction with the server, it may do nothing while waiting for the
      server to respond.

      When the "client" has the focus, the server may be processing at
      lower priority, and the two only seem to match speed because the client
      is blocked waiting for a response from the server (allowing the server
      to run at full speed until it sends the response).
      [color=blue]
      > Does anybody have an idea how can this be? Not that users will test 2
      > game intances communicating via localhost, but I need to make it work
      > properly.[/color]

      Define "work properly"... It sounds like they are working
      properly /as coded/ and are being affected by OS priority schemes. I
      say "as coded" since, as I mentioned in the first paragraph, it sounds
      like you have your server doing double duty -- both as a client and as
      the server for the second client. The server should not have ANY client
      type interface (other than start-up and shut-down or debug override
      commands). All frame-based rendering should be in the clients. I also
      suspect that, with two clients and a server, you'd see the same behavior
      -- the "non-input" client will be running at a lower priority, thereby
      achieving a lower frame-rate.

      It also sounds like your server is doing something like:

      loop
      if socket has data then
      read socket
      compute new state
      send reply
      end if
      do nasty computation
      end loop

      This logic will suck up as much CPU time as the OS will give the
      program... While if the client looks like

      loop
      send data to server
      read reply (blocking)
      do nasty computation
      end loop

      then it not only has to compete for CPU time, it does nothing while
      waiting for the server to handle the section inside the IF block.

      But what would happen if you put something like os.sleep(0.025)
      inside the loops? Assuming the loop takes 0.025sec to process, the total
      comes to 0.05 seconds (20fps) AND releases the CPU for the other process
      to compute.

      --[color=blue]
      > =============== =============== =============== =============== == <
      > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
      > wulfraed@dm.net | Bestiaria Support Staff <
      > =============== =============== =============== =============== == <
      > Home Page: <http://www.dm.net/~wulfraed/> <
      > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

      Comment

      • Michael Rybak

        #4
        Re[2]: 2-player game, client and server at localhost

        Thank you very much for your response, and may I point out some details:
        [color=blue][color=green]
        >> It works synchronously, but somehow, when I play in client window,
        >> both client and server have 17 fps, while when playing in server
        >> window, server has 44 fps while client has 5, and due to forced
        >> synchronization , they both run very slowly (I wonder how come server
        >> says it has 44fps?).
        >>[/color][/color]
        DLB> Well, for a 2 player game of this sort, I'd think there should
        DLB> be one server and TWO clients... It sounds more like you have a
        DLB> master-slave arrangement with the slave forced to synchronize to the
        DLB> master.
        Yes, that's what I have. I was already told I should have 1 server and
        2 clients, well I will, but I'd really like to make it work the
        master-slave way now.

        DLB> If you are running on Windows,
        Yes, I am

        To answer the rest of your message: the "client" and "server" (C and S
        below) are actually equal in my implementation. They both compute
        everything. I was told it's not smart to do that, but I can't see why
        is it better to have server compute everything: there are only 2
        players, and there's quite not much computations, while transferring
        current status is much more traffic-consuming than simply transferring
        user motions.

        Below I outline what S and C do:

        S:
        loop
        draw screen
        accept player1 input from mouse/kbd
        send player1 input to C
        process player1 input
        hang till C sends us player2 input
        process player2 input

        do the nasty computations :)
        end loop

        C:
        loop
        draw screen
        hang till S sends us player1 input
        process player1 input
        accept player2 input from mouse/kbd
        send player2 input to S
        process player2 input

        do the nasty computations :)
        end loop


        So you see C and S should cause equal load of CPU.
        By the way, yesterday a friend of mine kindly agreed to test the game
        online with me, and my God I was so happy to see it DID connected and
        we could play (yes, this is the first program in my 10+ years of
        programming that sends something over the web), but the speed is
        overwhelmingly dreadful, near 3 fps :), while my 1.2 Celeron said I
        had 21 fps, and his 3.0 Pentium said he had 120.

        He tends to think that my problem is that they both hang to wait for
        the input of each other, and that happens after each frame is drawn.
        Well, it is lame, but why does it work fine at my pc when client
        window is active?

        And another important note - he also tested 2 instances playing via
        localhost at his PC, and they both indeed had 35 fps, no matter which
        window was active. I believe he has hyperthreading turned on while I
        don't, but I wonder home come it wouldn't work without it? I've looked
        at my CPU load, and for C being active we have 45% for C/45% for S,
        while for S being active - 88% for S/ 11% for C :((

        I'd really welcome any suggestions, please.


        DLB> the program with the input focus is probably running at a higher
        DLB> priority... So the "server", when having input focus, gets to compute
        DLB> lots of stuff while the client gets less CPU time... and if the
        DLB> client then (whenever it does a frame say) does a transaction with
        DLB> the server, it may do nothing while waiting for the
        DLB> server to respond.

        DLB> When the "client" has the focus, the server may be processing at
        DLB> lower priority, and the two only seem to match speed because the client
        DLB> is blocked waiting for a response from the server (allowing the server
        DLB> to run at full speed until it sends the response).
        [color=blue][color=green]
        >> Does anybody have an idea how can this be? Not that users will test 2
        >> game intances communicating via localhost, but I need to make it work
        >> properly.[/color][/color]

        DLB> Define "work properly"... It sounds like they are working
        DLB> properly /as coded/ and are being affected by OS priority schemes. I
        DLB> say "as coded" since, as I mentioned in the first paragraph, it sounds
        DLB> like you have your server doing double duty -- both as a client and as
        DLB> the server for the second client. The server should not have ANY client
        DLB> type interface (other than start-up and shut-down or debug override
        DLB> commands). All frame-based rendering should be in the clients. I also
        DLB> suspect that, with two clients and a server, you'd see the same behavior
        DLB> -- the "non-input" client will be running at a lower priority, thereby
        DLB> achieving a lower frame-rate.

        DLB> It also sounds like your server is doing something like:

        DLB> loop
        DLB> if socket has data then
        DLB> read socket
        DLB> compute new state
        DLB> send reply
        DLB> end if
        DLB> do nasty computation
        DLB> end loop

        DLB> This logic will suck up as much CPU time as the OS will give the
        DLB> program... While if the client looks like

        DLB> loop
        DLB> send data to server
        DLB> read reply (blocking)
        DLB> do nasty computation
        DLB> end loop

        DLB> then it not only has to compete for CPU time, it does nothing while
        DLB> waiting for the server to handle the section inside the IF block.

        DLB> But what would happen if you put something like os.sleep(0.025)
        DLB> inside the loops? Assuming the loop takes 0.025sec to process, the total
        DLB> comes to 0.05 seconds (20fps) AND releases the CPU for the other process
        DLB> to compute.

        DLB> --
        DLB> > =============== =============== =============== =============== == <
        DLB> > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
        DLB> > wulfraed@dm.net | Bestiaria Support Staff <
        DLB> > =============== =============== =============== =============== == <
        DLB> > Home Page: <http://www.dm.net/~wulfraed/> <
        DLB> > Overflow Page: <http://wlfraed.home.ne tcom.com/> <



        --
        Best Regards,
        Michael Rybak mailto:accepted @ukr.net

        Comment

        • Dennis Lee Bieber

          #5
          Re: Re[2]: 2-player game, client and server at localhost

          On Sun, 31 Jul 2005 10:31:30 +0300, Michael Rybak <accepted@ukr.n et>
          declaimed the following in comp.lang.pytho n:
          [color=blue]
          > Yes, that's what I have. I was already told I should have 1 server and
          > 2 clients, well I will, but I'd really like to make it work the
          > master-slave way now.
          >[/color]
          [color=blue]
          >
          > To answer the rest of your message: the "client" and "server" (C and S
          > below) are actually equal in my implementation. They both compute
          > everything. I was told it's not smart to do that, but I can't see why
          > is it better to have server compute everything: there are only 2
          > players, and there's quite not much computations, while transferring
          > current status is much more traffic-consuming than simply transferring
          > user motions.
          >[/color]
          I don't know about your game, but the clients should be involved
          with the User Interface processing, responding to relatively short
          status messages involving those items that can be moved (if you have a
          scheme that is doing graphical destruction of the backgrounds too, you
          do have more data to transfer).

          The server should basically handle the multiple client
          connection logic, and determination of interactions between movable
          objects -- collision detection, for example (and I don't mean in the
          terms of graphics rendering but in terms of object one at current
          movement intersecting object two moving at some other vector).
          [color=blue]
          > Below I outline what S and C do:
          >
          > S:
          > loop
          > draw screen
          > accept player1 input from mouse/kbd
          > send player1 input to C
          > process player1 input
          > hang till C sends us player2 input[/color]

          ^^^^^^^^^^^^^^^ ^^^

          Neither should "hang" (block) for the other, since that will
          basically turn the system into a turn-based system (and turn-based
          systems don't really have "frame-rates").

          I'm also NOT a game programmer, so I'm not sure how well most of
          them separate screen updates from I/O, but I'd turn the above loop into
          something like:


          create screen thread
          create I/O thread

          {screen thread}
          loop:
          compute/display screen using snapshot of "local status"

          {I/O thread}
          loop
          if keyboard has activity
          read data
          send data to server
          if server has activity
          read data
          update local status

          Note that the keyboard, in this simple example, never affects
          the local (client) display -- only the status sent back by the server is
          used. Okay, you may need to process things like "quit" locally <G>.

          This scheme allows multiple keys/server updates to be captured
          without using a blocking operation (the I/O thread should use something
          like socket.select() -- but on Windows, that doesn't work for non-socket
          I/O streams... might need to create a keyboard thread and a socket
          thread, and have both use a "Queue" to transmit to the master I/O
          thread). The display update, however long it takes, uses an
          instantaneous snapshot of the "local status" (so things don't move while
          it computes the frame), but the frame computed will reflect all
          key/server activity that occurred.

          The server looks like:

          loop
          if new client connect
          add client to list of clients
          send client current status
          if data from client
          update world state (collision detects, damage, etc.)
          for c in client list
          send current status
          if client disconnect
          remove client from list


          Recall my warning -- I'm not a game programmer; this is just how
          /I'd/ consider implementing something like this.


          --[color=blue]
          > =============== =============== =============== =============== == <
          > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
          > wulfraed@dm.net | Bestiaria Support Staff <
          > =============== =============== =============== =============== == <
          > Home Page: <http://www.dm.net/~wulfraed/> <
          > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

          Comment

          • Michael Rybak

            #6
            Re[4]: 2-player game, client and server at localhost

            Again, thank you very much for your help.

            DLB> The server should basically handle the multiple client
            DLB> connection logic, and determination of interactions between movable
            DLB> objects -- collision detection, for example (and I don't mean in the
            DLB> terms of graphics rendering but in terms of object one at current
            DLB> movement intersecting object two moving at some other vector).

            My problem is: there are about 30 movable objects, so transferring
            all their coordinates is much more traffic consuming (about 150 bytes
            per transfer) rather than sending only user's motions (10 bytes per
            transfer). But on the other hand, sending user's motions between two
            non-server-neither-clients means that I needed stricted
            synchronization , which means the turn-based approach, as you've said.


            DLB> I'm also NOT a game programmer, so I'm not sure how well most of
            DLB> them separate screen updates from I/O, but I'd turn the above loop into
            DLB> something like:


            DLB> create screen thread
            DLB> create I/O thread

            DLB> {screen thread}
            DLB> loop:
            DLB> compute/display screen using snapshot of "local status"

            DLB> {I/O thread}
            DLB> loop
            DLB> if keyboard has activity
            DLB> read data
            DLB> send data to server
            DLB> if server has activity
            DLB> read data
            DLB> update local status

            DLB> Note that the keyboard, in this simple example, never affects
            DLB> the local (client) display -- only the status sent back by the server is
            DLB> used. Okay, you may need to process things like "quit" locally <G>.

            Well, this look really elegant, but will need me some time to rewrite
            my networking that way. Thank's a lot, I'll let you know when it
            works.

            [..snip..]

            ]DLB> The server looks like:

            DLB> loop
            DLB> if new client connect
            DLB> add client to list of clients
            DLB> send client current status
            DLB> if data from client
            DLB> update world state (collision detects, damage, etc.)
            DLB> for c in client list
            DLB> send current status
            DLB> if client disconnect
            DLB> remove client from list

            consider this part:
            DLB> if data from client
            DLB> update world state (collision detects, damage, etc.)
            DLB> for c in client list
            DLB> send current status
            the problem is - I should do this not "if data from client", but every
            50 milliseconds or so, because objects are still moving when not
            affected by users. To give you a better idea of what my game is:

            Each player controls a snake, which is 2 to 12 balls connected to each
            other with ropes; by mouse motions you move the snake's head, and the
            rest of the body moves adhering normal physics. The objective/gameplay
            is unimportant here, but if you're curios - all the balls of your
            snake are bullets, and right-clicking releases current tail. So, you
            have to spin around, and release the tail in appropriate moment so it
            reaches your opponent, causing as much damage as much impulse it had.
            There are health-pots and other stuff on game field of course.

            So, you see - server will have to send current status as much time per
            second, as much fps I want, and that's quite a lot of data.

            I'd also like to mention (if I haven't already) that I have a 33.6
            modem, while the friend I'm testing with has a 2 Mbit dedicated line,
            if this is the right term.


            I also was advised (by Peter Hansen) to try using Twisted, Pyro os
            something like that. I've looked at Pyro, and tried using it, without
            a lot of success compared to what I have now. I'm starting a new topic
            here, describing my experiment.


            DLB> Recall my warning -- I'm not a game programmer; this is just how
            DLB> /I'd/ consider implementing something like this.
            You're being very helpful anyway :)


            DLB> --
            DLB> > =============== =============== =============== =============== == <
            DLB> > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
            DLB> > wulfraed@dm.net | Bestiaria Support Staff <
            DLB> > =============== =============== =============== =============== == <
            DLB> > Home Page: <http://www.dm.net/~wulfraed/> <
            DLB> > Overflow Page: <http://wlfraed.home.ne tcom.com/> <



            --
            Best Regards,
            Michael Rybak mailto:accepted @ukr.net

            Comment

            • Dennis Lee Bieber

              #7
              Re: Re[4]: 2-player game, client and server at localhost

              On Mon, 1 Aug 2005 18:07:59 +0300, Michael Rybak <accepted@ukr.n et>
              declaimed the following in comp.lang.pytho n:

              [color=blue]
              > My problem is: there are about 30 movable objects, so transferring
              > all their coordinates is much more traffic consuming (about 150 bytes[/color]

              See below...
              [color=blue]
              > consider this part:
              > DLB> if data from client
              > DLB> update world state (collision detects, damage, etc.)
              > DLB> for c in client list
              > DLB> send current status
              > the problem is - I should do this not "if data from client", but every
              > 50 milliseconds or so, because objects are still moving when not
              > affected by users. To give you a better idea of what my game is:
              >[/color]
              That, unfortunately, gets back to the problem with select() on
              Windows -- though still work here as the "data from client" is presumed
              to be via socket... The select() call takes a timeout, so you could do
              motion updates if needed...
              [color=blue]
              > Each player controls a snake, which is 2 to 12 balls connected to each
              > other with ropes; by mouse motions you move the snake's head, and the
              > rest of the body moves adhering normal physics. The objective/gameplay[/color]

              For purposes of the motion this snake -- the game rendering side
              (the client) probably should handle the physics. The only part being
              actively controlled is the head, and only the head movement needs to be
              sent -- the clients respond to head movement and compute the effect on
              the rest of the body. IOW, the head and /attached/ balls are ONE object
              for purposes of server I/O, not "2 to 12".
              [color=blue]
              > is unimportant here, but if you're curios - all the balls of your
              > snake are bullets, and right-clicking releases current tail. So, you
              > have to spin around, and release the tail in appropriate moment so it[/color]

              At this point, you've added another object to track -- but it
              sounds like all you need to send is a vector (start position, direction,
              speed). The server, on each "input" can compute -- based on the
              situation at that moment -- if an intersect will occur, and when. That
              state doesn't change unless on or the other player inputs some new
              command (the target player, most likely, trying to avoid impact). Upon
              the new input, the server interpolates all moving objects -- that is,
              its prior update (time T0) says an intersect will occur at time T0+t,
              and the player response came in at t/2 (halfway, for simplicity). The
              server would compute positions for tracked objects at (T0+t/2), then
              apply the new motion vectors (player changed heading), transmit all this
              to all clients, and determine the next intersect time. The server
              doesn't have to do anything until either this intersect time or a play
              input comes in.
              [color=blue]
              > So, you see - server will have to send current status as much time per
              > second, as much fps I want, and that's quite a lot of data.
              >[/color]
              No... Frame rate is independent. Each client should perform some
              tests to determine what frame rate they can support, and adjust their
              internal time-steps to that. The server should probably send a
              time-stamp so clients can adjust for running over (might result in small
              jerks on slow machines, say). Of course, the server will need to check
              its clock speed to determine what size a time step will be (and maybe
              send that to clients so clients can compute a clock factor for internal
              calculations -- especially if the server is using a "simulation clock"
              for speed rather than wall clock time)

              Say the "snake" is moving left to right at 100 pixels (or some
              game internal unit) per second, and client one can only run 5FPS; that
              means each rendering pass uses the head position as:
              P(f) = P(T0) + (100/5)*f.
              {P(f) is Position(frame) ; P(T0) is the position at the start, the last
              status received from the server; 100/5 is the speed divided by the frame
              rate = speed per frame}

              The other client may be running 50FPS... For that client, the
              same status turns into:
              P(f) = P(T0) + (100/50)*f

              The first player sees the snake move 20 pixels per frame. The
              second player will see it move 2 pixels per frame, but will see 10
              frames in the time the first player sees one.

              In any event, the server is not continuously sending data. It
              only sends when it receives a client movement (which changes the state
              of the "world") or when a computed event has happened (a "bullet" has
              hit a target). "Bullets" are predictable; with no changes in from
              clients, the server can compute when the "bullet" will hit, and set up a
              timer for that event (canceling the time if a client moves).

              So, assuming something like select(in, out, sleep) [I may have
              in/out reversed]...

              loop
              if select(clients_ in, None, time_to_next_ev ent)
              if time_out
              compute damage
              if clients_data
              compute changes in state
              send updated states
              computer time_to_next_ev ent


              Ah well, I'm late for work... need to run....

              --[color=blue]
              > =============== =============== =============== =============== == <
              > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
              > wulfraed@dm.net | Bestiaria Support Staff <
              > =============== =============== =============== =============== == <
              > Home Page: <http://www.dm.net/~wulfraed/> <
              > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

              Comment

              • Michael Rybak

                #8
                Re[6]: 2-player game, client and server at localhost

                sorry for emailing privately, pressed the wrong "reply" button
                [color=blue][color=green]
                >> Each player controls a snake, which is 2 to 12 balls connected to each
                >> other with ropes; by mouse motions you move the snake's head, and the
                >> rest of the body moves adhering normal physics. The objective/gameplay[/color][/color]

                DLB> For purposes of the motion this snake -- the game rendering side
                DLB> (the client) probably should handle the physics. The only part being
                DLB> actively controlled is the head, and only the head movement needs to be
                DLB> sent -- the clients respond to head movement and compute the effect on
                DLB> the rest of the body. IOW, the head and /attached/ balls are ONE object
                DLB> for purposes of server I/O, not "2 to 12".
                Well, that's exactly how I think of it.
                [color=blue][color=green]
                >> is unimportant here, but if you're curios - all the balls of your
                >> snake are bullets, and right-clicking releases current tail. So, you
                >> have to spin around, and release the tail in appropriate moment so it[/color][/color]

                DLB> At this point, you've added another object to track -- but it
                DLB> sounds like all you need to send is a vector (start position, direction,
                DLB> speed). The server, on each "input" can compute -- based on the
                DLB> situation at that moment -- if an intersect will occur, and when. That
                DLB> state doesn't change unless on or the other player inputs some new
                DLB> command (the target player, most likely, trying to avoid impact).
                But that happens all the time, and lots of times per second! If you
                played Quake, CS or even UT :), you know that you hold your "forward"
                key pressed all the time, and you also move your mouse aiming on
                target almost all the time. And when I play Quake, I *see* how my
                opponent's model aims at me, I mean, his mouse motions are transferred
                to me.
                Well, I suppose that Quake doesn't send mouse motion, clients
                probably retrieve the resulting aiming direction from server, but in
                my case, as you said yourself, client side should do physics'
                computations.

                DLB> Upon the new input, the server interpolates all moving objects -- that is,
                DLB> its prior update (time T0) says an intersect will occur at time T0+t,
                DLB> and the player response came in at t/2 (halfway, for simplicity). The
                DLB> server would compute positions for tracked objects at (T0+t/2), then
                DLB> apply the new motion vectors (player changed heading), transmit all this
                DLB> to all clients, and determine the next intersect time. The server
                DLB> doesn't have to do anything until either this intersect time or a play
                DLB> input comes in.
                That's the problem - "or a player input comes in". As I've explained,
                this happens a dozen of times per second :(. I've even tried not
                checking for player's input after every frame, but do it 3 times more
                rare (if framecount % 3 == 0 : process_players _input()). Well, I've
                already got it that I shouldn't tie this around framerate, but
                nevertheless...
                [color=blue][color=green]
                >> So, you see - server will have to send current status as much time per
                >> second, as much fps I want, and that's quite a lot of data.
                >>[/color][/color]
                DLB> No... Frame rate is independent. Each client should perform some
                DLB> tests to determine what frame rate they can support, and adjust their
                DLB> internal time-steps to that. The server should probably send a
                DLB> time-stamp so clients can adjust for running over (might result in small
                DLB> jerks on slow machines, say). Of course, the server will need to check
                DLB> its clock speed to determine what size a time step will be (and maybe
                DLB> send that to clients so clients can compute a clock factor for internal
                DLB> calculations -- especially if the server is using a "simulation clock"
                DLB> for speed rather than wall clock time)
                I'm afraid I'm loosing it. Let's consider your example:

                DLB> Say the "snake" is moving left to right at 100 pixels (or some
                DLB> game internal unit) per second, and client one can only run 5FPS; that
                DLB> means each rendering pass uses the head position as:
                DLB> P(f) = P(T0) + (100/5)*f.
                DLB> {P(f) is Position(frame) ; P(T0) is the position at the start, the last
                DLB> status received from the server; 100/5 is the speed divided by the frame
                DLB> rate = speed per frame}

                DLB> The other client may be running 50FPS... For that client, the
                DLB> same status turns into:
                DLB> P(f) = P(T0) + (100/50)*f

                DLB> The first player sees the snake move 20 pixels per frame. The
                DLB> second player will see it move 2 pixels per frame, but will see 10
                DLB> frames in the time the first player sees one.

                This sounds transparent, but my slow client isn't able to process
                networking fast enough, so even if it's able to work at 30 fps, it
                can't draw those 30 frames, because input from other player comes
                instantly, about 10 times per second, and server tries sending this to
                all clients. So my slow client simply can't know current true status,
                thus has nothing to draw, because it can't handle 10 transfers per
                second. And if server doesn't send user motions equal number of times
                to all clients, while they compute the world's status, they will
                happen to have different pictures :(



                --
                Best Regards,
                Michael Rybak mailto:accepted @ukr.net

                Comment

                • Christopher Subich

                  #9
                  Re: 2-player game, client and server at localhost

                  Michael Rybak wrote:[color=blue]
                  > That's the problem - "or a player input comes in". As I've explained,
                  > this happens a dozen of times per second :(. I've even tried not
                  > checking for player's input after every frame, but do it 3 times more
                  > rare (if framecount % 3 == 0 : process_players _input()). Well, I've
                  > already got it that I shouldn't tie this around framerate, but
                  > nevertheless...[/color]

                  There's the key. How are you processing network input, specifically
                  retrieving it from the socket?

                  Comment

                  • Michael Rybak

                    #10
                    Re[2]: 2-player game, client and server at localhost

                    CS> Michael Rybak wrote:[color=blue][color=green]
                    >> That's the problem - "or a player input comes in". As I've explained,
                    >> this happens a dozen of times per second :(. I've even tried not
                    >> checking for player's input after every frame, but do it 3 times more
                    >> rare (if framecount % 3 == 0 : process_players _input()). Well, I've
                    >> already got it that I shouldn't tie this around framerate, but
                    >> nevertheless...[/color][/color]

                    CS> There's the key. How are you processing network input, specifically
                    CS> retrieving it from the socket?

                    A "sock" class has a socket with 0.00001 timeout, and every time I
                    want anything, I call it's read_command() method until it returns
                    anything. read_command() and send_command() transfer user's actions in
                    special format so that it takes 10 bytes per transfer.


                    I believe this should be rewritten to be done in a separate thread, and
                    that *current* user input should be processed as *next* one:
                    while 1:
                    render()
                    inp = get_player_inpu t()
                    thread.start_ne w(send_inp, (inp,))
                    thread.start_ne w(accept_oppone nts_inp, ())
                    while still_no_oppone nts_input_from_ previous_iterat ion()
                    time.sleep(0.05 )
                    process_previou s_player_input( )
                    physics.make_st ep

                    I will try writing it that way, but I doubt it shall make things much
                    better... You see, I've tried the normal 1-server-2-clients approach
                    with Pyro (and today with simulating RMI proxy via UDP), and resulted
                    with nothing comforting. Please read the "using Pyro for network
                    games" topic here for details.

                    --
                    Best Regards,
                    Michael Rybak mailto:accepted @ukr.net

                    Antivirus alert: file .signature infected by signature virus.
                    Hi! I'm a signature virus! Copy me into your signature file to help me spread!




                    P.S. here's the sock class. My server_sock and client_sock are derived
                    from it, with additional accept_connecti on and establish_conne ction
                    methods respectively.

                    #sock.py
                    import socket
                    import com_network
                    import constants as c_


                    class sock:
                    def __init__(self, host):
                    self.host = host
                    self.port = c_._PORT

                    self.sockobj = socket.socket(s ocket.AF_INET, socket.SOCK_STR EAM)
                    self.sockobj.se ttimeout(0.0000 1)

                    self.curcon = None #connection will be created and saved here
                    self.connected = False

                    def read_command(se lf):
                    """format:
                    command_id - 1 byte
                    command_size - CMD_LEN_BIT_SIZ E bytes
                    command_text - command_size bytes

                    returns a triple (int id, int size, str text)"""

                    if not self.connected:
                    return (None, None)
                    cmd = com_network.rea d_fixed(self.cu rcon, 1)
                    if len(cmd) < 1: #no cmd
                    return (None, None)
                    sz = com_network.rea d_fixed(self.cu rcon, CMD_LEN_BIT_SIZ E)
                    cmd, sz = str_to_cmd(cmd + sz)
                    text = com_network.rea d_fixed(self.cu rcon, sz)
                    return (cmd, text)

                    def send_command(se lf, cmd, obj):
                    send_text(self. curcon, com_network.cmd _to_str(cmd, str(obj)))


                    def close(self):
                    if self.connected:
                    self.connected = False
                    self.curcon.clo se
                    self.curcon = None
                    self.sockobj.cl ose()

                    Comment

                    • Dennis Lee Bieber

                      #11
                      Re: Re[6]: 2-player game, client and server at localhost

                      On Tue, 2 Aug 2005 10:16:13 +0300, Michael Rybak <accepted@ukr.n et>
                      declaimed the following in comp.lang.pytho n:

                      [color=blue]
                      > But that happens all the time, and lots of times per second! If you
                      > played Quake, CS or even UT :), you know that you hold your "forward"
                      > key pressed all the time, and you also move your mouse aiming on[/color]

                      Are you sure the server or client isn't smoothing things out...
                      For example, holding down your "forward" button may just mean the client
                      sent ONE "forward ON" at the start, and doesn't send anything more until
                      you release the key (when it sends a "forward OFF"). Could also smooth
                      mouse movements, only sending them when they jitter far enough from some
                      point.
                      [color=blue]
                      > Well, I suppose that Quake doesn't send mouse motion, clients
                      > probably retrieve the resulting aiming direction from server, but in
                      > my case, as you said yourself, client side should do physics'
                      > computations.[/color]

                      The server most likely is transmitting just the position and
                      facing (direction) information -- 6 numeric values (XYZ position, XYZ
                      direction/speed vector). If the game is really starved for time, they
                      could be mapping directions to bytes -- 0..360degrees mapped to 0..255,
                      meaning the smallest direction change handled is 360/255 => ~1.4deg.
                      That means the direction vector is only 3 bytes long. Position is
                      probably 16-bit each, unsigned, allowing 0..65536 discrete positions in
                      each direction. Things like controlling arms & legs could be solely
                      client side -- if the "body" center standing up is +4 units (assume a
                      unit is "foot"), then a body center that is only 2 units above the
                      "floor" must be crouching. Walking too -- the client "knows" the
                      position has changed by x-units in some direction; the client animates
                      leg movement "knowing" that the legs must be on the "floor" and below
                      the body by some margin (say +/- 2 units for a four foot stride).

                      [color=blue]
                      > That's the problem - "or a player input comes in". As I've explained,
                      > this happens a dozen of times per second :(. I've even tried not
                      > checking for player's input after every frame, but do it 3 times more
                      > rare (if framecount % 3 == 0 : process_players _input()). Well, I've
                      > already got it that I shouldn't tie this around framerate, but
                      > nevertheless...
                      >[/color]
                      The input data should be processed without being tied to frame
                      rate... The frame update should only use the /most recent/ data...
                      Essentially, you throw out anything that you couldn't process in time --
                      which means the slowest client /will/ look jerky.

                      Even for your simple 2-D snakes, two snakes and say four "shots"
                      is six objects. Six objects of: (ID, Type, (px, py, pz), (vx, vy, vz))
                      and using 16-bit ints results in 16 bytes per object, 96 bytes to update
                      the "world"... Add some packet overhead and call it 128 bytes. On a
                      28.8Kbps modem (with no compression, 10bits per byte), you should get
                      2880 bytes/second, or 22 "world updates" per second. And those should
                      take very little CPU time to just parse and update the object states
                      {pseudocode}
                      object(ID).upda te(position, velocity)

                      The start of the frame update would make snapshot (deepcopy) of
                      all objects so they don't change during the frame computation. Even
                      while the frame computation is taking place, you should be accepting
                      updates from the server -- they just don't have any effect: if you are
                      getting five frames/second for display, and server updates at 22/second
                      (call it 20) then you will have four
                      object(ID).upda te(position, velocity)
                      passes per frame -- only the last one will be around when the next frame
                      begins.

                      Your clients may need to know what comm-rate they have, and
                      inform the server not to send data faster than can be streamed. There's
                      no sense having a server sending DSL rate (over 220 updates/second, say,
                      if it will take 10 seconds for your end to read them).


                      [color=blue]
                      > This sounds transparent, but my slow client isn't able to process
                      > networking fast enough, so even if it's able to work at 30 fps, it
                      > can't draw those 30 frames, because input from other player comes
                      > instantly, about 10 times per second, and server tries sending this to[/color]

                      DisplayThread I/OThread
                      T0 frame -
                      T0+1 frame -
                      T0+2 frame update
                      T0+3 frame-using-new -
                      T0+4 frame -
                      T0+5 frame update
                      T0+6 frame-using-new
                      etc

                      There shouldn't be that much data in an update... Even on a slow
                      dialup client it could receive some 20 world updates per second (+ or -
                      depending on how many actual "shots" are in motion). These updates
                      should only be data copies into the "world object" map... The only real
                      computations are in the frame display. The frame display has to be
                      extrapolating in between updates anyways.
                      [color=blue]
                      > all clients. So my slow client simply can't know current true status,
                      > thus has nothing to draw, because it can't handle 10 transfers per
                      > second. And if server doesn't send user motions equal number of times
                      > to all clients, while they compute the world's status, they will
                      > happen to have different pictures :([/color]

                      That's likely what happens in the other games too -- but the
                      differences are close enough not to be apparent. The primary factor is
                      that the client has to be synchronized to the same simulation /time/.
                      Everything else in extrapolated from position/velocity (velocity
                      includes direction) at time T0 to the frame time T0+t

                      The only real case where one can not extrapolate over a time
                      span is when the server (which should be the fastest machine in the
                      system) has determined an intersection has occurred. If the server says
                      a "bullet" has hit a "target", it should identify both the bullet and
                      target and the client must respond appropriately with a "hit" reaction.
                      The client can't just go from "bullet" in front of "target" to "bullet"
                      behind "target" just because that is where the frame update says it now
                      is.


                      If your slower client is being swamped by world updates, then
                      you likely must implement a throttle in the server logic. Each client
                      reports the rate at which they can receive updates, and the server only
                      sends updates to that client at that rate. Again, this may mean for
                      highly mismatched clients, that the slow client may only get one update
                      for every 10 that the fast client gets.

                      Something rudimentary like having the server send 10 seconds
                      worth of "typical" world updates with time stamps... So server data for
                      first and last packets should be

                      T0, T0+10sec

                      and maybe that was 100 world updates (10/sec)

                      Slow client receives the first at T0, but the last (packet 100) comes in
                      at T0+60. Fast client receives all packets in T0+10...

                      It took 60 seconds to receive 10 seconds of data. Client sends
                      back to server a rate of 6. Other client sends back rate of 1.

                      Server now uses a modulo function on packet sends...

                      for c in client
                      if t mod c.rate = 0
                      send current world packet to client


                      You may want to throttle the server anyways -- say only send an
                      update every 0.1 second


                      (time to go to work -- and I still haven't showered!)
                      --[color=blue]
                      > =============== =============== =============== =============== == <
                      > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
                      > wulfraed@dm.net | Bestiaria Support Staff <
                      > =============== =============== =============== =============== == <
                      > Home Page: <http://www.dm.net/~wulfraed/> <
                      > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

                      Comment

                      • Christopher Subich

                        #12
                        Re: 2-player game, client and server at localhost

                        Michael Rybak wrote:[color=blue]
                        > CS> There's the key. How are you processing network input, specifically
                        > CS> retrieving it from the socket?
                        >
                        > A "sock" class has a socket with 0.00001 timeout, and every time I
                        > want anything, I call it's read_command() method until it returns
                        > anything. read_command() and send_command() transfer user's actions in
                        > special format so that it takes 10 bytes per transfer.[/color]

                        So when you want player input, you explicitly halt the program until you
                        receive it, inside a while loop? No wonder your programs aren't
                        behaving well, then.

                        Network processing Is Not Slow. Unless you're sending near the maximum
                        capacity of your line, which you're obviously not[1], the slowness is
                        architectural.

                        [1] - The TCP packet contains at most 28 bytes of overhead, so combine
                        that with 10 bytes of data and you're looking at 38 bytes/packet. A
                        33.6 modem can handle 4.2kB/sec, cut that in half for a safety margin
                        for 2.1kB/sec. That will handle about 55 updates/second, which you
                        shouldn't be reaching if you're "just sending updates when a player does
                        something."

                        Why are you messing with sockets directly, to begin with? It looks like
                        you want an asynchronous socket interface, so that you don't explicitly
                        loop and wait for data from the nyetwork for updates.

                        In addition to making Julienne fries, Twisted is an excellent framework
                        for asynchronous network IO. For a naive, non-threaded implementation,
                        you'd schedule your update code as a timed event, and you'd define a
                        Protocol for handling your network stuff. When you receive data, the
                        protocl would update your application's state, and that would be picked
                        up automagically the next time your update event ran.

                        In a threaded implementation, you'd run your update code to a thread
                        (DeferToThread) , and your network code would post updates to a
                        synchronous queue, read by your update code.

                        Comment

                        • Dennis Lee Bieber

                          #13
                          Re: Re[2]: 2-player game, client and server at localhost

                          On Tue, 2 Aug 2005 19:31:55 +0300, Michael Rybak <accepted@ukr.n et>
                          declaimed the following in comp.lang.pytho n:
                          [color=blue]
                          > while 1:
                          > render()[/color]
                          [color=blue]
                          > inp = get_player_inpu t()
                          > thread.start_ne w(send_inp, (inp,))
                          > thread.start_ne w(accept_oppone nts_inp, ())[/color]

                          You don't understand threading either, it appears. Here you are
                          starting a new thread for each input you want... There should just be AN
                          input thread, started at the very beginning, and it should just wait for
                          input, then update the global state so the "update step" can do
                          whatever.

                          Also, recommend you use threading, not thread as the module.

                          SERVER
                          An input thread would look something like:

                          while True:
                          data = socket.read() #assumes both clients write to same socket
                          #otherwise use a select(client_s ocket_list)
                          #followed by socket.read for the flagged socket(s)
                          parse data
                          lock global
                          save in global state variables
                          unlock global

                          That is all

                          Update thread
                          while True:
                          lock global
                          copy state variables to local
                          unlock global
                          compute new world state (check for collisions -- "bullet" hits)
                          for c in client_list
                          send world state to c

                          CLIENT
                          User-input thread
                          while True:
                          ch = keyboard
                          compute effect of ch
                          send controlled object(s) state to server

                          server-input thread
                          while True:
                          world_state = socket.read
                          lock global
                          update global with world_state
                          unlock global

                          rendering thread
                          while True:
                          lock global
                          copy global world_state to local
                          unlock global
                          render graphics based on local world_state

                          main "thread"

                          connect to server
                          get initial world state -- may include static stuff (background map)
                          start rendering thread
                          start server-input thread
                          start user-input thread
                          wait(until dead)


                          The client rendering thread (and server update thread) only see
                          the most recent state of data at the top of the loop.
                          [color=blue]
                          > while still_no_oppone nts_input_from_ previous_iterat ion()
                          > time.sleep(0.05 )[/color]
                          You're still focused on a turn based system, it looks like...[color=blue]
                          > process_previou s_player_input( )
                          > physics.make_st ep
                          >[/color]

                          --[color=blue]
                          > =============== =============== =============== =============== == <
                          > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
                          > wulfraed@dm.net | Bestiaria Support Staff <
                          > =============== =============== =============== =============== == <
                          > Home Page: <http://www.dm.net/~wulfraed/> <
                          > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

                          Comment

                          • Michael Rybak

                            #14
                            Re[4]: 2-player game, client and server at localhost

                            I was a bit unhappy to read this, because what you describe here is
                            just what I've tried yesterday in my test-game with 2 balls, so if
                            I've pointed that out, you wouldn't have to say I
                            DLB> don't understand threading either, it appears.
                            :'(

                            Thank you very much for putting so much effort in making things clear
                            to me, *this* email of your made everything clear as never. Still I
                            have problems, and hope you still don't mind me asking.

                            Some comments:
                            [color=blue][color=green]
                            >> while 1:
                            >> render()[/color][/color]
                            [color=blue][color=green]
                            >> inp = get_player_inpu t()
                            >> thread.start_ne w(send_inp, (inp,))
                            >> thread.start_ne w(accept_oppone nts_inp, ())[/color][/color]

                            DLB> You don't understand threading either, it appears. Here you are
                            DLB> starting a new thread for each input you want...
                            and
                            [color=blue][color=green]
                            >> while still_no_oppone nts_input_from_ previous_iterat ion()
                            >> time.sleep(0.05 )[/color][/color]
                            DLB> You're still focused on a turn based system, it looks like...

                            Now, that's *not* how I'm tending to do it; that's what I was thinking
                            of while trying the turn-based approach, and describing here;
                            Christopher Subich asked how it was done initially, so I brought my
                            hanging system out of shame again, and added something I was thinking
                            about to improve it, while I already realize that's not the way to go
                            - from your previous comprehensive posts.


                            DLB> There should just be AN input thread, started at the very beginning,
                            DLB> and it should just wait for input, then update the global state so
                            DLB> the "update step" can do whatever.

                            As stated above, that's how I'm trying it right now. Still, if doing
                            it turn-base, I would have to create a new thread every time.
                            I have some other questions though - please see below.

                            DLB> Also, recommend you use threading, not thread as the module.
                            Surely will, why?

                            DLB> SERVER
                            DLB> An input thread would look something like:

                            DLB> while True:
                            DLB> data = socket.read() #assumes both clients write to same socket
                            DLB> #otherwise use a select(client_s ocket_list)
                            DLB> #followed by socket.read for the flagged socket(s)
                            DLB> parse data
                            DLB> lock global
                            DLB> save in global state variables
                            DLB> unlock global

                            Now, few questions. Do I need to time.sleep(0.xx x) in any of these
                            while True: loops, not to overwhelm CPU? I can measure the time at
                            beginning and end of each iteration to make things happen fixed number
                            of times per second, but should I? And another: do I get it right that
                            instead of "lock global" you mean:
                            while global.locked:
                            time.sleep(0.00 1)
                            lock global
                            And I also wonder how do I make sure that 2 threads don't pass this
                            "while" loop simultaneously and both try locking global. There is a
                            probability, not?

                            Now, for update thread:

                            DLB> That is all

                            DLB> Update thread
                            DLB> while True:
                            DLB> lock global
                            DLB> copy state variables to local
                            DLB> unlock global
                            DLB> compute new world state (check for collisions -- "bullet" hits)
                            DLB> for c in client_list
                            DLB> send world state to c

                            In my yesterday experiment, I have a separate thread for each of 2
                            clients, and what I do there is:

                            def thr_send_status (player_sock):
                            while 1:
                            t, sub_addr = player_sock.rec vfrom(128) #player ready to accept
                            player_sock.sen dto(encode_stat us(g.get_status ()), sub_addr)

                            I'm reading 1 byte from client every time before sending new update to
                            him. OK, Ok, I know that's not good, ok. Now, I like your idea much
                            more, where you say we first measure the processing speed of each
                            client, and send data to every client as often as he can process it:

                            DLB> Slow client receives the first at T0, but the last (packet 100) comes in
                            DLB> at T0+60. Fast client receives all packets in T0+10...

                            DLB> It took 60 seconds to receive 10 seconds of data. Client sends
                            DLB> back to server a rate of 6. Other client sends back rate of 1.

                            DLB> Server now uses a modulo function on packet sends...

                            DLB> for c in client
                            DLB> if t mod c.rate = 0
                            DLB> send current world packet to client


                            Yes, this I great, but what if speed changes? Should I retest this
                            around every 10 seconds? I mean, server sending too much data to a
                            client is ok for server, but very bad for a client, since it starts
                            hanging and loses synchronization , unless I use a timestamp to throw
                            away late states (I think I need to re-read all your previous posts,
                            you've explained about synchronizing already).
                            While thinking about this, I've decided to go the wrong way, and to
                            wait for confirmation from client before sending next pack.

                            Still, it shouldn't slow anything a lot, because client does this:

                            def thr_get_status( self, g, player_sock, player_id):
                            while 1:
                            player_sock.sen dto("!", addr) #ready
                            self.local_stat us = decode_status(p layer_sock.recv from(128)[0])
                            g.set_status(se lf.local_status )


                            So they simply exchange data all the time in separate threads, even
                            through separate sockets (not to dispatch the confirmations from
                            different players into corresponding threads via global flags), which
                            makes the "ready" thing ok from speed point of view, but I prefer
                            your way, quoted above, so my question is still valid - do I
                            remeasure speed?

                            I'm also almost sure it's wrong to have separate sockets and threads
                            for each player, you say I should select()/dispatch instead, but I'm
                            afraid of that some *thing* being wrong with select() for Windows.
                            Somehow, I'm doing a lot of thins the wrong way :(


                            Before describing another problem I've encountered, I thought I'd
                            remind you of what my test game is: each player controls it's ball by
                            moving mouse pointer, towards which his ball starts moving; that's it.

                            When I first tried this with threads, 1 client ran nearly perfect. But
                            when running 2 clients via localhost, they eat cpu away, and bad things
                            happen.

                            Now, you see, sending user motions to server appears to be faster (or
                            at least not slower) than getting new status, so, as a result, I have
                            the following picture: I place my pointer somewhere, and the ball runs
                            to it, and then runs a bit beyond it, because by the moment server
                            knows the ball is already at my pointer, client still thinks it's not.

                            Several seconds later, thins "a bit beyond" becomes "a lot beyond",
                            and finally both balls run away from game field, being helpless; seems
                            like I/O thread being much more productive than send_status one?

                            I thought that the reason is my stupid "ready" check before every
                            status update, and removed it. As a result, even single client via
                            local host was very slow, but no artifacts.

                            This all was when I had *no* time.sleeps in the while 1: loops.
                            So I added time.sleep(0.00 5) to server's send_status loop and to
                            client's send_user_actio n loop. Things became better, but still balls
                            are spinning around the mouse pointer instead of running under it.
                            Every time client tries moving towards the mouse, it's ball is already
                            at another place at server, and it runs in wrong direction.

                            Obviously, if I have these problems in such a primitive test at
                            localhost, I shouldn't even try running it online with the Snakes :(


                            Thanks again for being this helpful, Dennis, and thank you for your
                            patience!


                            --
                            Best Regards,
                            Michael Rybak mailto:accepted @ukr.net

                            Antivirus alert: file .signature infected by signature virus.
                            Hi! I'm a signature virus! Copy me into your signature file to help me spread!

                            Comment

                            • Christopher Subich

                              #15
                              Re: 2-player game, client and server at localhost

                              Michael Rybak wrote:
                              [color=blue]
                              > As stated above, that's how I'm trying it right now. Still, if doing
                              > it turn-base, I would have to create a new thread every time.
                              > I have some other questions though - please see below.[/color]

                              No, you should never need to create a new thread upon receiving input.
                              What you want is inter-thread communication, a synchronous queue.

                              A synchronous queue is a thread-safe queue. You'd push event updates to
                              it from the communication thread, and in the update thread, WHICH IS
                              ALWAYS RUNNING, you'd check the queue each loop to see if there was
                              anything new.
                              [color=blue]
                              > Now, few questions. Do I need to time.sleep(0.xx x) in any of these
                              > while True: loops, not to overwhelm CPU? I can measure the time at
                              > beginning and end of each iteration to make things happen fixed number
                              > of times per second, but should I? And another: do I get it right that
                              > instead of "lock global" you mean:
                              > while global.locked:
                              > time.sleep(0.00 1)
                              > lock global
                              > And I also wonder how do I make sure that 2 threads don't pass this
                              > "while" loop simultaneously and both try locking global. There is a
                              > probability, not?[/color]

                              You have the right idea, that locking's important, but when the
                              grandparent poster said "lock global," he meant "lock global." Locks
                              are low-level primitives in any threading system, they can also be
                              called mutexes.

                              Attempting to acquire a lock returns immediate if the lock can be
                              acquired; if it can't (and it's set to block, which is the default) the
                              thread will wait until it -can- acquire the lock -- the entire thrust of
                              your 'time.sleep' loop, only good.

                              See thread.acquire and threading.Lock for python built-in locks.
                              [color=blue]
                              > In my yesterday experiment, I have a separate thread for each of 2
                              > clients, and what I do there is:
                              >
                              > def thr_send_status (player_sock):
                              > while 1:
                              > t, sub_addr = player_sock.rec vfrom(128) #player ready to accept
                              > player_sock.sen dto(encode_stat us(g.get_status ()), sub_addr)
                              >
                              > I'm reading 1 byte from client every time before sending new update to
                              > him. OK, Ok, I know that's not good, ok. Now, I like your idea much
                              > more, where you say we first measure the processing speed of each
                              > client, and send data to every client as often as he can process it:[/color]

                              Just how much data are you sending in each second? Testing client speed
                              and managing updates that way is relatively advanced, and I'd argue that
                              it's only necessary when your data has the potential to swamp a network
                              connection.
                              [color=blue]
                              > While thinking about this, I've decided to go the wrong way, and to
                              > wait for confirmation from client before sending next pack.[/color]

                              No, you definitely don't need to do this. TCP is a reliable protocol,
                              and so long as the connection stays up your client will receive data
                              in-order with guaranteed arrival.

                              If you were using UDP, then yes you'd need (possibly) to send
                              confirmation, but you'd probably need a more advanced version to handle
                              missing / out-of-order packets.
                              [color=blue]
                              > I'm also almost sure it's wrong to have separate sockets and threads
                              > for each player, you say I should select()/dispatch instead, but I'm
                              > afraid of that some *thing* being wrong with select() for Windows.
                              > Somehow, I'm doing a lot of thins the wrong way :([/color]

                              Just use the Twisted library. It abstracts that away, and not touching
                              sockets is really much nicer.
                              [color=blue]
                              > Before describing another problem I've encountered, I thought I'd
                              > remind you of what my test game is: each player controls it's ball by
                              > moving mouse pointer, towards which his ball starts moving; that's it.[/color]

                              What's the nature of your evend update? Do you say "mouse moved N" or
                              "mouse moved to (123,456)?" If it's the latter, then without motion
                              prediction there's no way that either simulation should have the ball
                              overshoot the mouse. Synchronization , however, will still be an issue.

                              Comment

                              Working...