Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Reduce Packet Lag... Add a Packet Bufferi
#1
Originally posted by Verrigan

Difficulty: Medium 3/5

This tutorial is designed to show you how to put a buffer system in your game. Why would you want to do that? Think about it. When a player connects, there are a series of messages sent to that player, and in Mirage, they are sent one right after the other.. If you have large maps, or you have a bunch of items/npcs/spells/etc., the server will send all that data to a user who is connecting.. For small games with small sized maps, this isn't a problem.. Lag is minimal. However, for games with tons of items, spells, etc., you will experience lag when another player connects.

Okay, now introduce a buffering (queue) system.. The server form has a timer that calls a subroutine that is solely responsible for dropping the size of the queue. How does the queue get filled? Instead of immediately sending any data to a player, you make the server add it to the queue. The server then hits the timer's interval, calls the subroutine to drop the queue, which sends messages to each user that is waiting for those messages. The subroutine will go through all connections, check the queue, and deliver messages to each user up to a predefined size limit for each user.. (This tutorial limits that size to 32K per user, per loop, but you can easily customize that limit.)

All that said, I must say that I have only tested this buffer system with one connection, so it might need some work, which is why I set the difficulty at 3.. Some of you might think the difficulty should be 5, but that's why I'm going to tell you this: BACKUP YOUR SERVER BEFORE ADDING THIS TUTORIAL.

Now, on with the tutorial..

Files to Modify
  • frmServer.frm
  • modGeneral.bas
  • modServerTCP.bas
  • modTypes.bas
*** In addition to the above files, you will need to change any line from:
Code:
Call CloseSocket()
to:
Code:
QueueDisconnect() = True

frmServer.frm
FrmServer is where timers and sockets are stored.. I don't like to do this, but my tutorials are based on the already existing code in the Mirage Source, not redoing the whole thing.. Tongue So...

Add a timer to the form named: tmrStartMsgQueue with an interval of 100. Then, in the code of frmServer, add the following code:
Code:
Private Sub tmrStartMsgQueue_Timer()
  Call SendQueuedData
End Sub

modGeneral.bas
ModGeneral is where general stuff happens.. The server is initialized here, the AI is in here, etc.

Add the following code somewhere:
Code:
Sub SendQueuedData()
  Dim i As Integer, n As Long
  Dim TmpStr As String
  
  For i = 1 To MAX_PLAYERS

    TmpStr = ""
    With ConQueues(i)
      If Not .Lock Then
        If frmServer.Socket(i).State  7 Then
          .Lines = ""
        End If
        If Len(.Lines) = 0 And QueueDisconnect(i) = True Then
          Call CloseSocket(i)
          QueueDisconnect(i) = False
        Else
          If Len(.Lines) > 0 Then
             If Len(.Lines) < MAX_PACKETLEN Then
               TmpStr = .Lines
             Else
               TmpStr = Left(.Lines, MAX_PACKETLEN)
             End If
             .Lines = Right(.Lines, Len(.Lines) - Len(TmpStr))
          End If
        End If
        If Len(TmpStr) > 0 Then
          Call frmServer.Socket(i).SendData(TmpStr)
        End If
      End If
    End With
  Next
  DoEvents
End Sub
In Sub InitServer
After this code:
Code:
' Init all the player sockets
    For i = 1 To MAX_PLAYERS
        Call SetStatus("Initializing player array...")
        Call ClearPlayer(i)
        
        Load frmServer.Socket(i)
add this code:
Code:
ConQueues(i).Lines = "" 'Initialize the lines.

modServerTCP.bas
ModServerTCP handles the data being sent from/received to the server.

In Sub SendDataTo()
Change this code:
Code:
If IsConnected(Index) Then
        frmServer.Socket(Index).SendData Data
        DoEvents
    End If
to this code:
Code:
If IsConnected(Index) Then
        With ConQueues(Index)
          .Lock = True
          .Lines = .Lines & Data
          .Lock = False
        End With
        'DoEvents
    End If

modTypes.bas
ModTypes is where all the data types are stored, and other stuff...

Under this code:
Code:
Type GuildRec
    Name As String * NAME_LENGTH
    Founder As String * NAME_LENGTH
    Member(1 To MAX_GUILD_MEMBERS) As String * NAME_LENGTH
End Type
add this code:
Code:
Type ConDataQueue
  Lock As Boolean
  Lines As String
End Type

Public ConQueues(MAX_PLAYERS) As ConDataQueue
Public Const MAX_PACKETLEN As Long = 32768 'About 32K
Public QueueDisconnect(MAX_PLAYERS) As Boolean

This was tested in a vanilla Mirage Source 3.0.3. So, if you add this to your game, and I only tested this with one player connected.. (I don't have a bunch of users, cause I don't run a Mirage server.. Tongue) Anyways.. Just like any other tutorials on here... BACKUP YOUR SOURCE!!! I said it twice, now... Hopefully you will take my advice..

It is also possible that I failed to put something in here.. In the event that you find that I forgot something, or you tried this in a vanilla server and it didn't work.. Please post here, but I'm pretty sure I remembered everything.. Smile
Reply


Messages In This Thread

Forum Jump:


Users browsing this thread: 1 Guest(s)