FreeFry Posted June 4, 2007 Share Posted June 4, 2007 (edited) Hi, I've coded this little Server Monitor app, but there's a problem.It is very heavy on the cpu with only 3-4 servers..I'd appreciate if anyone could take the time to look @ it, and give me a suggestion of what I could improve on it. Oh and btw. this is for Half-Life1 servers(CS 1.6, etc. but I think source servers is ok too though, can't remember right now.)Edit:Alternatively I maybe could use this instead(to do the server queries):http://home.arcor.de/levelad/SSQbeta1.zipEdit2:Fixed, code updated.expandcollapse popup#include <String.au3> #include <GuiConstants.au3> #include <Constants.au3> #NoTrayIcon UDPStartup() Opt("WinTitleMatchMode", 4) Opt("WinWaitDelay", 0) Opt("GUIDataSeparatorChar", @LF) Opt("TrayMenuMode",1) Opt("GUIOnEventMode", 1) Opt("TrayOnEventMode", 1) Dim $DebugMode = True Dim $A2S_INFO = _HexToString("FFFFFFFF") & "TSource Engine Query" & _HexToString("00") ; Retrives server name and stuff(needs handle) Dim $A2S_SERVERQUERY_GETCHALLENGE = _HexToString("FFFFFFFF57") ; Retrives a handle Dim $A2S_RULES = _HexToString("FFFFFFFF56") ; Retrives a server's rules(needs handle) Dim $SettingsDir = @AppDataDir & "\FreeSoft\Server Monitor" Dim $OnTopAttribute Dim $ServerList [1] = [0] Dim $ListViewItems[1][2] = [[0]] Dim $TimerHandle = TimerInit() Dim $GuiHandle = GuiCreate("Server Monitor v1.0", 691, 30,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS)) $List_1 = GUICtrlCreateListView("Name" & @LF & "Players" & @LF & "Map" & @LF & "Ping" & @LF & "Address", 0, 0, 690, 40) $Tray_Item1 = TrayCreateItem("Always on top", -1, -1, 0) $Tray_Item2 = TrayCreateItem("Add Server", -1, -1) $Tray_Item4 = TrayCreateItem("Connect", -1, -1) $Tray_Item3 = TrayCreateItem("Exit", -1, -1) GUISetOnEvent($GUI_EVENT_CLOSE, "_HandleGUI") TrayItemSetOnEvent($Tray_Item1, "_HandleTray") TrayItemSetOnEvent($Tray_Item2, "_HandleTray") TrayItemSetOnEvent($Tray_Item3, "_HandleTray") TrayItemSetOnEvent($Tray_Item4, "_HandleTray") GuiSetState() TraySetState() _LoadSettings() _ToggleOnTopState() While 1 If TimerDiff($TimerHandle) > 2000 Then _UpdateServerList() $TimerHandle = TimerInit() EndIf Sleep(100) WEnd Func _HandleGUI() Local $GuiMsg = @GUI_CTRLID If $GuiMsg = $GUI_EVENT_CLOSE Then _SaveSettings() Exit EndIf EndFunc Func _HandleTray() Local $TrayMsg = @TRAY_ID If $TrayMsg = $Tray_Item3 Then _SaveSettings() Exit ElseIf $TrayMsg = $Tray_Item4 Then _Connect() ElseIf $TrayMsg = $Tray_Item1 Then _ToggleOnTopState() ElseIf $TrayMsg = $Tray_Item2 Then _AddServer() EndIf EndFunc Func _Connect() Local $i_SelectedLVI = GUICtrlRead($List_1) If $DebugMode Then ConsoleWrite("Connecting to listviewitem: " & $i_SelectedLVI & @LF) EndIf If $ListViewItems[0][0] = 1 Then MsgBox(0, "Error", "Please add servers first!") Return ElseIf $i_SelectedLVI = 0 Then MsgBox(0, "Error", "Please select a server first!") Return EndIf For $i = 1 To $ListViewItems[0][0] If $ListViewItems[$i][0] = $i_SelectedLVI Then ShellExecute("steam://connect/" & $ListViewItems[$i][1]) EndIf Next EndFunc Func _AddServer($s_ServerAddress = "") Local $a_ServerInfo Local $i_ListViewItem If $s_ServerAddress = "" Then $s_ServerAddress = InputBox("Server Address", "Input the server address and port, ex: 194.18.96.169:27015") If @error Then Return EndIf If $DebugMode Then ConsoleWrite("Adding server: " & $s_ServerAddress & @LF) EndIf $a_ServerInfo = _GetServerInfo($s_ServerAddress) If @error Then MsgBox(0, "Error", "Server: " & $s_ServerAddress & " is not responding, skipping") Return EndIf $i_ListViewItem = GUICtrlCreateListViewItem($a_ServerInfo[0] & @LF & $a_ServerInfo[3] & @LF & $a_ServerInfo[2] & @LF & $a_ServerInfo[6] & @LF & $a_ServerInfo[7], $List_1) $ServerList[0] += 1 ReDim $ServerList[$ServerList[0]+1] $ServerList[$ServerList[0]] = $s_ServerAddress $ListViewItems[0][0] += 1 ReDim $ListViewItems[$ListViewItems[0][0]+1][2] $ListViewItems[$ListViewItems[0][0]][0] = $i_ListViewItem $ListViewItems[$ListViewItems[0][0]][1] = $a_ServerInfo[7] EndFunc Func _UpdateServerList() Local $a_ServerInfo If $DebugMode Then ConsoleWrite("Updating serverlist..." & @LF) EndIf For $i = 1 To $ServerList[0] $a_ServerInfo = _GetServerInfo($ServerList[$i]) If @error Then ContinueLoop GUICtrlSetData($ListViewItems[$i][0], $a_ServerInfo[0] & @LF & $a_ServerInfo[3] & @LF & $a_ServerInfo[2] & @LF & $a_ServerInfo[6]) Next EndFunc Func _LoadSettings() Global $WindowPosition = IniRead($SettingsDir & "\Settings.ini", "Settings", "Position", -1) Global $OnTopAttribute = IniRead($SettingsDir & "\Settings.ini", "Settings", "AoT", True) Global $WindowSize = IniRead($SettingsDir & "\Settings.ini", "Settings", "Size", -1) If $DebugMode Then ConsoleWrite("Loading settings..." & @LF) EndIf Local $a_ServerList = IniReadSection($SettingsDir & "\Settings.ini", "Servers") $a_ServerList = IniReadSection($SettingsDir & "\Settings.ini", "Servers") If Not @error Then For $i = 1 To $a_ServerList[0][0] _AddServer($a_ServerList[$i][1]) Next EndIf If $WindowPosition <> -1 Then $WindowPosition = StringSplit($WindowPosition, ",") $WindowSize = StringSplit($WindowSize, ",") If Not @error Then WinMove($GuiHandle, "", $WindowPosition[1], $WindowPosition[2], $WindowSize[1], $WindowSize[2]) Else WinMove($GuiHandle, "", $WindowPosition[1], $WindowPosition[2]) EndIf EndIf If $OnTopAttribute = "True" Then $OnTopAttribute = True ElseIf $OnTopAttribute = "False" Then $OnTopAttribute = False EndIf EndFunc Func _SaveSettings() Local $WindowPosition = WinGetPos($GuiHandle) If $DebugMode Then ConsoleWrite("Saving settings..." & @LF) EndIf If Not FileExists($SettingsDir) Then DirCreate($SettingsDir) For $i = 1 To $ServerList[0] IniWrite($SettingsDir & "\Settings.ini", "Servers", $i, $ServerList[$i]) Next IniWrite($SettingsDir & "\Settings.ini", "Settings", "Size", $WindowPosition[2] & "," & $WindowPosition[3]) IniWrite($SettingsDir & "\Settings.ini", "Settings", "Position", $WindowPosition[0] & "," & $WindowPosition[1]) IniWrite($SettingsDir & "\Settings.ini", "Settings", "AoT", Not $OnTopAttribute) EndFunc Func _ToggleOnTopState() WinSetOnTop($GuiHandle, "", Number($OnTopAttribute)) If $DebugMode Then ConsoleWrite("Toggling AllwaysOnTop State" & @LF) EndIf If $OnTopAttribute Then TrayItemSetState($Tray_Item1, $TRAY_CHECKED) Else TrayItemSetState($Tray_Item1, $TRAY_UNCHECKED) EndIf $OnTopAttribute = Not $OnTopAttribute EndFunc ;~ $rServerInfo[0] = $ServerName ;~ $rServerInfo[1] = $ServerType ;~ $rServerInfo[2] = $ServerMap ;~ $rServerInfo[3] = $ServerPlayers ;~ $rServerInfo[4] = $ServerSlots ;~ $rServerInfo[5] = $ServerIsPass ;~ $rServerInfo[6] = $ServerPing Func _GetServerInfo($sServer); ip:port Local $sIP = StringLeft($sServer, StringInStr($sServer, ":", 0, -1)-1) Local $sPort = StringTrimLeft($sServer, StringInStr($sServer, ":", 0, -1)) Local $ServerInfo = _QueryServerInfo($sIP, $sPort) ;~ If $ServerInfo <> -1 Then ;~ $sPing = Ping($sIP, 5000); Fast, though less accurate results ;~ $sPing = Int((Ping($sIP, 500)+Ping($sIP, 500)+Ping($sIP, 500)+Ping($sIP, 500))/4); Hmmm.. takes very long time... but more accurate results ;~ Else If Not IsArray($ServerInfo) Then SetError(1) Return -1 EndIf ;~ If $sPing = 0 Then ;~ SetError(2) ;~ EndIf Return $ServerInfo EndFunc Func _QueryServerInfo($t_ServerIp, $t_ServerPort, $t_TimeOut = 5000) Local $oSocket = UDPOpen($t_ServerIp, $t_ServerPort) Local $Data Local $ServerType Local $ServerName Local $ServerMap Local $ServerPlayers Local $ServerSlots Local $ServerIsPass Local $ServerPing Local $rServerInfo[8] If $oSocket = -1 Then SetError(@error) Return -1 EndIf _UDPSendData($oSocket, $A2S_INFO) ;~ $Data = UDPRecv($oSocket, 9999) $Data = BinaryToString(_UDPReceiveData($oSocket, $t_TimeOut*2, 9999)) If @error Then SetError(@error) Return $Data EndIf ;~ MsgBox(0, "$Data, Error: " & @error, $Data) If StringLeft($Data, 4) == _HexToString("FFFFFFFF") Then $Data = StringTrimLeft($Data, 4) If StringLeft($Data, 1) == "I" Then $ServerType = "Source" ElseIf StringLeft($Data, 1) == "m" Then $ServerType = "Normal" EndIf $Data = StringTrimLeft($Data, 1) If $ServerType = "Normal" Then Do $Data = StringTrimLeft($Data, 1); Trim Ip and Port Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) Do $ServerName = $ServerName & StringLeft($Data, 1) $Data = StringTrimLeft($Data, 1) Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) Do $ServerMap = $ServerMap & StringLeft($Data, 1) $Data = StringTrimLeft($Data, 1) Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) Do $Data = StringTrimLeft($Data, 1); Trim GameDir Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) Do $Data = StringTrimLeft($Data, 1); Trim Description Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) $ServerPlayers = Asc(StringLeft($Data, 1)) $Data = StringTrimLeft($Data, 1) $ServerSlots = Asc(StringLeft($Data, 1)) $Data = StringTrimLeft($Data, 4) $ServerIsPass = Asc(StringLeft($Data, 1)) If String($ServerIsPass) = "1" Then $ServerIsPass = "Yes" Else $ServerIsPass = "No" EndIf ElseIf $ServerType = "Source" Then $Data = StringTrimLeft($Data, 1); Trim version Do $ServerName = $ServerName & StringLeft($Data, 1) $Data = StringTrimLeft($Data, 1) Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) Do $ServerMap = $ServerMap & StringLeft($Data, 1) $Data = StringTrimLeft($Data, 1) Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) Do $Data = StringTrimLeft($Data, 1); Trim GameDir Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 1) Do $Data = StringTrimLeft($Data, 1); Trim Description Until StringLeft($Data, 1) = Chr(0) $Data = StringTrimLeft($Data, 3); Trim nul char & AppID $ServerPlayers = Asc(StringLeft($Data, 1)) $Data = StringTrimLeft($Data, 1) $ServerSlots = Asc(StringLeft($Data, 1)) $Data = StringTrimLeft($Data, 4) $ServerIsPass = Asc(StringLeft($Data, 1)) If String($ServerIsPass) = "1" Then $ServerIsPass = "Yes" Else $ServerIsPass = "No" EndIf EndIf $ServerPing = Ping($t_ServerIp, $t_TimeOut) If $ServerPing = 0 Then $ServerPing = -1 Else MsgBox(0, "Error", "Wrong data received from server.") UDPCloseSocket($oSocket) SetError(1) Return -3 EndIf ;~ $rServerInfo = "ServerName: " & $ServerName & @CRLF & "ServerType: " & $ServerType & @CRLF & "Map: " & $ServerMap & @CRLF & "Players: " & $ServerPlayers & "/" & $ServerSlots & @CRLF & "Password Required: " & $ServerIsPass ;~ Return $rServerInfo UDPCloseSocket($oSocket) $rServerInfo[0] = $ServerName $rServerInfo[1] = $ServerType $rServerInfo[2] = $ServerMap $rServerInfo[3] = $ServerPlayers $rServerInfo[4] = $ServerSlots $rServerInfo[5] = $ServerIsPass $rServerInfo[6] = $ServerPing $rServerInfo[7] = $t_ServerIp & ":" & $t_ServerPort Return $rServerInfo EndFunc Func _UDPReceiveData($o_Socket, $m_TimeOut = 5000, $s_BufferSize = 999) Local $r_data Local $t_Handle = TimerInit() Do $r_data = UDPRecv($o_Socket, $s_BufferSize) Until $r_data <> "" Or TimerDiff($t_Handle) > $m_TimeOut Or @error If @error Then SetError(@error) ; Other Error Return -2 ; Other Error ElseIf TimerDiff($t_Handle) > $m_TimeOut Then SetError(1) ; Timed Out Return -1 ; Timed Out EndIf Return $r_data ; No error EndFunc Func _UDPSendData($o_Socket, $s_Data) Local $n_Data = UDPSend($o_Socket, $s_Data) SetError(@error) If @error = 1 Then Return -1 ; Ip-adress error ElseIf @error = 2 Then Return -2 ; Port error ElseIf @error Then Return -3 ; Other error EndIf Return $n_Data ; No error EndFunc Edited June 4, 2007 by FreeFry Link to comment Share on other sites More sharing options...
enaiman Posted June 4, 2007 Share Posted June 4, 2007 What I can see ... there is no Sleep in your While loop. Update your loop like: While 1 Sleep (250) If TimerDiff($TimerHandle) > 2000 Then _UpdateServerList() $TimerHandle = TimerInit() EndIf WEnd and see what's happening - my guess it is that your CPU load will drop significantly. You can experiment with different values for Sleep to see which suits you. SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script wannabe "Unbeatable" Tic-Tac-Toe Paper-Scissor-Rock ... try to beat it anyway :) Link to comment Share on other sites More sharing options...
FreeFry Posted June 4, 2007 Author Share Posted June 4, 2007 That helped, thanks. lol I recently updated it to use the OnEventMode instead of the usual gui/tray 'message polling', and I guess I forgot that part. Hmm, though still, it uses quite much cpu usage when it's updating the server list. :/ Link to comment Share on other sites More sharing options...
enaiman Posted June 4, 2007 Share Posted June 4, 2007 Glad it worked One question: do you need to update the server list every 2 seconds? If TimerDiff($TimerHandle) > 2000 Then I think this way too fast ... make it like 30 sec or whatever you like and this will also free your CPU. I didn't check your code for how this update is done (and never will because I don't know too much about this). SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script wannabe "Unbeatable" Tic-Tac-Toe Paper-Scissor-Rock ... try to beat it anyway :) Link to comment Share on other sites More sharing options...
FreeFry Posted June 4, 2007 Author Share Posted June 4, 2007 Hmm, 30 is way to slow in my opinion, but I'm not sure, never made an app like this before. Link to comment Share on other sites More sharing options...
enaiman Posted June 4, 2007 Share Posted June 4, 2007 Hmm, 30 is way to slow in my opinion, but I'm not sure, never made an app like this before.30 was like an example - you can use any value - I just wanted to say that updating every 2 seconds is a bit too fast.If you change that for 4 sec instead of 2 it will free your CPU a little - just experiment and see what's best. SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script wannabe "Unbeatable" Tic-Tac-Toe Paper-Scissor-Rock ... try to beat it anyway :) Link to comment Share on other sites More sharing options...
FreeFry Posted June 11, 2007 Author Share Posted June 11, 2007 (edited) I think the problem with it stressing the cpu was because first I tried to use msg polling with the gui instead of the event thing, and that actually made it totally hang after a while, then when I sat down and changed it into using events it worked good, except that it was a little laggy. It actually works flawless now, I had just forgot the sleep in the main loop. xD Only thing about the update delay that I'm actually concerned about is so that it doesn't spam the server with requests. Edit: As the source is available for free(as all my apps) for anyone that wants it with a greater delay can change it. Thanks for you input though! Edited June 11, 2007 by FreeFry Link to comment Share on other sites More sharing options...
codydbgt Posted April 6, 2011 Share Posted April 6, 2011 (edited) dam onece again I'm sorry wrong post Edited April 6, 2011 by codydbgt Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now