PHP-Serverliste

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Starwar

Betreff: PHP-Serverliste

BeitragSa, Mai 08, 2010 18:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,
Hier eine kleine PHP-Serverliste für Blitzbasic.
Beispiel im Blitz-Code.


Kurze Erklärung zur Funktionsweise:
1. Client fragt PHP-Script nach Servern und bekommt eine Liste mit IP, Port und einer ID je Server.
2. Client kontaktiert alle Server (das musst Du einprogrammieren, Funktion serverOnline(...) im BB-Code)
3. Der Client meldet dem Skript welche Server online und welche offline sind.
4. Wenn 3 unterschiedliche Clients gemeldet haben, dass der Server nicht verfügbar ist, wird er aus der Datenbank gelöscht. Wer diese Zahl ändern will guckt mal bei der Funktion couldNotConnect im PHP-Teil)

Implementierung:
1. Datenbank anlegen
2. Login- und Ordner-Daten im PHP-Script und Blitz-Code anpassen
3. PHP-Code hochladen
4. Testen
5. serverOnline(...)-Funktion anpassen

Quellcodes
PHP-Script
Code: [AUSKLAPPEN]
<?php
$database = ""; //Datenbank (Server ist unten eingetragen)
$password=""; //Passwort
$table="games"; //Tabelle

$action=$_GET['action'];
$id=$_GET['id'];
$offIDs=$_GET['offids'];
$onIDs=$_GET['onids'];
$hash=$_GET['hash'];
$ip=$_GET['ip'];
$port=$_GET['port'];
$millisecs=$_GET['millisecs'];

echo("[START]\n");
$verbindung=connect("localhost", $database, $password);

$action = mysql_real_escape_string($action);
$id = mysql_real_escape_string($id);
$offIDs = mysql_real_escape_string($offIDs);
$onIDs = mysql_real_escape_string($onIDs);
$hash = mysql_real_escape_string($hash);
$port = mysql_real_escape_string($port);
$millisecs = mysql_real_escape_string($millisecs);

switch ($action){
    case 'get':getGames($table);
    case 'new':addGame($table,$ip,$port,$millisecs);
        case 'del':deleteGameHashCheck($id, $table, $hash);
            case 'sna':couldNotConnect($id, $ip, $table);
                case 'sce':serverOnline($id,$table);
                    case 'ssr':meldeServer($ip, $onIDs, $offIDs, $table);
                    default:echo("-- Unknown command");
}

mysql_close($verbindung);
echo("\n[ENDE]");



function getGames($table) {
    $abfrage = "SELECT * FROM '$table' ORDER BY $table.ID";
    $ergebnis = mysql_query($abfrage);
    $err = mysql_error();
    if ($err != "") {
        echo "-- $err\n";
        return;
    }
    while($row = mysql_fetch_object($ergebnis)) {
//        $rem = autoRemove($table, $row);
//        if ($rem == false) {
        echo ("+$row->ID|$row->IP|$row->Port\n");
//        }
    }
    echo ("++\n");
    return;
}

function addGame($table, $ip, $port, $millisecs) {
    if ($port=="" || $ip == "" || $millisecs=="") {
        echo("-- Ungültige Argumente\n");
        return;
    }
    //$stamp=time();
    $hash="$ip|$port|$stamp|$millisecs";
    $hash=md5($hash,false);
    $sqlrows="HASH,IP,Port,ErrorCount,ErrorIPs";//,LastPing";
    $sqlvals="'$hash','$ip','$port','0',''";//,'$stamp'";
    $eintrag ="INSERT INTO $table ($sqlrows) VALUES ($sqlvals)";
    mysql_query($eintrag);
    $err = mysql_error();
    if ($err != "") {
        echo ("-- $err\n");
    } else {
        $gameID=mysql_insert_id();
        echo ("+$gameID|$hash\n++\n");
    }
    return;
}


function meldeServer($meldeIP,$idsOnline,$idsOffline,$table) {
    //Akzeptiert IDs als Liste (; ist Trennzeichen)
    if ($idsOnline != "") {
        $idOn = explode(";",$idsOnline);
        foreach ($idOn as &$id) {
            serverOnline($id, $table);
        }
    }
    if ($idsOffline != "") {
        $idOff = explode(";",$idsOffline);
        foreach ($idOff as &$id) {
            couldNotConnect($id, $meldeIP, $table);
        }
    }
}

function serverOnline($id,$table) {
    $abfrage = "SELECT * FROM '$table' WHERE ID = '$id' ";
    $ergebnis=mysql_query($abfrage);
    $err = mysql_error();
    if ($err != "") {
        return;
    }
    $count="0";
    $ipString = "";
    $abfrage2 = "UPDATE '$table' Set ErrorCount = '$count' WHERE ID = '$id' ";
    $ergebnis2=mysql_query($abfrage2);
    $err2 = mysql_error();
    $abfrage2 = "UPDATE '$table' Set ErrorIPs = '$ipString' WHERE ID = '$id' ";
    $ergebnis2=mysql_query($abfrage2);
    $err2 = mysql_error();
}

function couldNotConnect($id, $IPdesMelders, $table) {
    $max=3;

    $abfrage = "SELECT * FROM '$table' WHERE ID = '$id' ";
    $ergebnis=mysql_query($abfrage);
    $err = mysql_error();
    if ($err != "") {
        return;
    }
    $row = mysql_fetch_object($ergebnis);
    $ipString=$row->ErrorIPs;
    if ($ipString == "") {
        $ips[]="";
    } else {
        $ips=explode(";",$ipString);
    }
    $report=true;
    foreach ($ips as &$cur) {
        if ($cur==$IPdesMelders) {
            $report=false;
        }
    }
    if ($report) {
        $count=$row->ErrorCount;
        $count++;
        if ($count > $max) {
            deleteGame($id, $table, true);
        } else {
            if (empty($ipString)) {
                $ipString = $IPdesMelders;
            } else {
                $ipString = "$ipString;$IPdesMelders";
            }
            $abfrage2 = "UPDATE '$table' Set ErrorCount = '$count' WHERE ID = '$id' ";
            $ergebnis2=mysql_query($abfrage2);
            $err2 = mysql_error();
            $abfrage2 = "UPDATE '$table' Set ErrorIPs = '$ipString' WHERE ID = '$id' ";
            $ergebnis2=mysql_query($abfrage2);
            $err2 = mysql_error();
        }
    }
}

function connect($serv, $db, $pw) {
    $verbindung=mysql_connect($serv,$db,$pw) or die
            ("--\n");
    mysql_select_db($db) or die
            ("--\n");
    return $verbindung;
}

function deleteGameHashCheck($id, $table, $hash) {
    $abfrage = "SELECT * FROM '$table' WHERE ID = '$id' ";
    $ergebnis=mysql_query($abfrage);
    $err = mysql_error();
    if ($err != "") {
        echo ("-- $err\n");
        return;
    }
    $row = mysql_fetch_object($ergebnis);
    $h=$row->HASH;
    if($h == $hash) {
        deleteGame($id, $table);
        return;
    } else {
        echo ("-- $err\n");
        return;
    }
}

function deleteGame($id, $table, $noecho) {
    $abfrage = "DELETE FROM '$table' WHERE ID = '$id' ";
    $ergebnis=mysql_query($abfrage);
    $err = mysql_error();
    if ($err != "") {
        if($noecho) {
            return;
        }
        echo ("-- $err\n");
        return;
    }
    if($noecho) {
        return;
    }
    echo ("++\n");
    return;
}
?>


BlitzBasic
Code: [AUSKLAPPEN]
;Informationen zur Serverregistrierung
Global phpserver_reg=False
Global phpserver_id%=0
Global phpserver_hash$=""

;Type für die Serverliste
Type phpserver_Server
   ;Diese Felder werden im Code verwendet
   Field id%
   Field ip%
   Field port%
   ;Diese sind überflüssig und nur für Testzwecke (-> serverOnline(...))
   Field name$
   Field players%
   Field maxplayers%
   Field ping%
End Type


;Testinformationen
server$="du.server.de" ;entspricht dem Host
site$="/ordner/serverliste.php" ;Link zum Script
myip%=Rand(10000,990000)
myport%=Rand(10,90)



;Server registrieren Test
ok = phpserver_registerServer(server$, site$, myip%, myport%)
If ok=True Then
   Print "ID: "+phpserver_id%
   Print "Hash: "+phpserver_hash$
   Print "Adresse: "+myip%+":"+myport%
Else
   Print "Fehler beim erstellen des Servers"
EndIf

;Serverlisten-Test
ok = phpserver_getServerlist(server$,site$, myip%)
If ok = True Then
   For s.phpserver_Server = Each phpserver_Server
      Print s\name$+" | "+s\players+"/"+s\maxplayers+" | "+s\id+" | "+s\ping+" | "+s\ip%+":"+s\port%+"
   Next
Else
   Print "Fehler"
EndIf

;Server-löschen Test
Print "Löschtest: "+phpserver_unRegisterServer(server$, site$, phpserver_id%, phpserver_hash$)

WaitKey
End


;Meldet einen Server ab (Host, Link zum Script, serverID, serverHash)
;Liefert true bei Erfolg
Function phpserver_unRegisterServer(server$,site$, id%, hash$)
   answer$ = phpserver_internal_request$(server$, site$+"/?action=del&id="+id%+"&hash="+hash$)
   If Instr(answer$,"--") Or answer="" Then
      phpserver_reg=True ;<-- Ist die Frage ob man den Fehlversuch nicht einfach ignorieren soll
      Return False
   Else
      phpserver_reg=False
   EndIf
   Return True
End Function


;meldet einen Server an (Host, Link zum Script, IP des Servers als Int, Port des Servers)
;Liefert true bei Erfolg
Function phpserver_registerServer(server$, site$, myip%, myport%)
   answer$ = phpserver_internal_request$(server$, site$+"/?action=new&ip="+myip%+"&port="+myport%+"&millisecs="+MilliSecs())
   If Instr(answer$,"--") Or answer="" Then
      phpserver_reg=False
      Return False
   Else
      anz=phpserver_internal_explodeCount(answer$,"@")
      For i=0 To anz-1
         cur$=phpserver_internal_explode(answer$,"@",i)
         If Left(cur$,1)="+" And Left(cur$,2)<>"++" Then
            phpserver_reg=True
            phpserver_id%=Int(Mid(cur$,2,Instr(cur$,"|")-2))
            phpserver_hash$=Mid(cur$,Instr(cur$,"|")+1,-1)
         EndIf
      Next
   EndIf
   Return True
End Function


;Lädt die Serverliste in den Type (Host, Link zum Script, IP des Anfragestellers als Int)
;Liefert true bei Erfolg
Function phpserver_getServerlist(server$,site$,myip%)
   Delete Each phpserver_Server
   answer$ = phpserver_internal_request$(server$, site$+"/?action=get")
   If Instr(answer$,"--") Or answer="" Then
      Return False
   Else
      anz=phpserver_internal_explodeCount%(answer$,"@")
      For i=0 To anz-1
         cur$=phpserver_internal_explode(answer$,"@",i)
         If Left(cur$,1)="+" And Left(cur$,2)<>"++" Then
            ex$=Mid(cur$,2,-1)
            s.phpserver_Server=New phpserver_Server
            s\id%=Int(Trim(phpserver_internal_explode$(ex$,"|",0)))
            s\ip%=Int(Trim(phpserver_internal_explode$(ex$,"|",1)))
            s\port%=Int(Trim(phpserver_internal_explode$(ex$,"|",2)))
            If serverOnline(ip%,port%,s) Then
               onString$=onString$+s\id%+";"
            Else
               offString$=offString$+s\id%+";"
               Delete s
            EndIf
         EndIf
      Next
      If Right(onString$,1)=";" Then onString$=Left(onString$,Len(onString)-1)
      If Right(offString$,1)=";" Then onString$=Left(offString$,Len(onString)-1)
      phpserver_internal_request$(server$,site$+"/?action=ssr&ip="+myip%+"&offids="+offString$+"&onids="+onString$)
   EndIf
   Return True
End Function


;Kontaktiert den Server über UDP und fragt Spielinformationen ab
;(IP des Servers als Int, Port desd Servers, Object)
;Liefert ob der Server verfügbar ist (True/False)
Function serverOnline(ip%,port%,server.phpserver_Server)
   ;///////////////////////////////////////////////////
   ;HIER HAST DU ARBEIT ;)
   ;Es sollte ein Timeout eingebaut werden
   ;///////////////////////////////////////////////////
   server\name$=Chr(Rand(65,90))+Chr(Rand(65,90))+Chr(Rand(65,90))
   server\players=5
   server\maxplayers=Rand(5,9)
   server\ping=Rand(15,99)
   Return Rand(0,1) ;<- Ist der Server online?
End Function


;Allemeine Anfrage an das Script(Host, Link zum Script mit Args)
;Liefert den Text zwischen [START] und [ENDE]. Zeilentrennung durch @
Function phpserver_internal_request$(server$, site$)
   tcp = OpenTCPStream(server$,80)
   If Not tcp Then Return "-- No Connection"
   
   WriteLine tcp,"GET "+site$+" HTTP/1.1"
   WriteLine tcp,"Host: "+server$
   WriteLine tcp,"User-Agent: Opera/9.80 (Windows NT 6.0; U; de) Presto/2.2.15 Version/10.10"
   WriteLine tcp,"Connection: close"
   WriteLine tcp,"Accept: */*"
   WriteLine tcp, Chr$(10)
   
   Local start=False
   txt$=""
   
   lin$ = ReadLine(tcp)
   If Not Instr(lin$,"200") Then Return "-- "+lin$
   
   Repeat
      lin$ = ReadLine(tcp)
      If lin$="[ENDE]" Then start=False
      If start Then
         lin$=Replace(lin$,Chr(10),"")
         lin$=Replace(lin$,Chr(13),"")
         If lin$ <> "" Then
            txt$=txt$+lin$+"@"
         EndIf
      EndIf
      If lin$ = "[START]" Then start=True
   Until Eof(tcp)
   
   If Right(txt$,1)="@" Then txt$=Left(txt$,Len(txt$)-1)
   
   CloseTCPStream(tcp)
   Return txt$
End Function     


Function phpserver_internal_explodeCount%(in$,tz$)
   pos=Instr(in$,tz$)
   If pos=0 Then
      Return 1
   EndIf
   Repeat
      pos=Instr(in$,tz$,pos+1)
      If Mid(in$,altpos+1,pos-1-altpos) <> "" Then anz=anz+1
      If pos = 0 Then Exit
   Forever
   Return anz
End Function


Function phpserver_internal_explode$(in$,tz$, index%)
   pos=0
   altpos=0
   exploded$=""
   Repeat
      altpos=pos
      pos=Instr(in$,tz$,pos+1)
      If pos = 0 Then pos=-1
      If Mid(in$,altpos+1,pos-1-altpos) <> "" Then
         If index%=i% Then
            exploded$=Mid(in$,altpos+1,pos-1-altpos)
            Exit
         EndIf
         i%=i%+1
      EndIf
      If pos=-1 Then Exit
   Forever
   Return exploded$
End Function


Function INT_IP(ip$)
   p1=Instr(ip$,".")
   p2=Instr(ip$,".",p1+1)
   p3=Instr(ip$,".",p2+1)
   Return (Int(Mid(ip$,1,p1))*16777216)+(Int(Mid(ip$,p1+1,p2-p1))*65536)+(Int(Mid(ip$,p2+1,p3-p2))*256)+Int(Mid(ip$,p3+1,-1))
End Function


Und der SQL-Code zum Erzeugen der Datenbank
Code: [AUSKLAPPEN]
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

CREATE TABLE IF NOT EXISTS `games` (
  `ID` int(11) NOT NULL auto_increment,
  `HASH` text NOT NULL,
  `IP` int(11) NOT NULL,
  `Port` int(11) NOT NULL,
  `ErrorCount` int(11) NOT NULL default '0',
  `ErrorIPs` text NOT NULL COMMENT 'Getrennt durch ;',
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


Ich hab noch manuell Änderungen am Code vorgenommen. Wenn jemand einen (Tipp-)Fehler findet wäre ich ihm/ihr sehr verbunden.
MFG

EDIT 1.7.2010
- Änderungen am PHP-Code (strlen, switch, '$table')
- Änderungen am BB-Code (Name ersetzt)
  • Zuletzt bearbeitet von Starwar am Do, Jul 01, 2010 19:43, insgesamt 3-mal bearbeitet
 

Düsi

BeitragFr, Jun 25, 2010 22:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Mal wird eine Variable deutsch benannt, mal gibt man ihr einen englischen Namen. Mal wird eine Variable komplett klein geschrieben, dann werden die Wörter wieder mit _ getrennt und beim nächsten Mal schreibt man wieder jedesWortAmAnfangGross.

Zum PHP Code:
-> Wieso verdammt gibst du einen Doctype an?!
-> ' ist schneller als " (hier wird geprüft, ob sich Variablen im String befinden), weswegen dies auch verwendet werden sollte.
-> In Querys sollten Tabellen- und Spaltennamen immer zwischen zwei ` stehen, da somit Konflikte mit der Syntax von MySQL vermieten werden.

Code: [AUSKLAPPEN]
if ($action == "get") {
    getGames($table);
} else if ($action == "new") {
    addGame($table,$ip,$port,$millisecs);
} else if ($action=="del") {
    deleteGameHashCheck($id, $table, $hash);
} else if ($action == "sna") {
    couldNotConnect($id, $ip, $table);
} else if ($action == "sce") {
    serverOnline($id,$table);
}  else if ($action=="ssr") {
    meldeServer($ip, $onIDs, $offIDs, $table);
} else {
    echo("-- Unknown command");
}

Wie wärs damit?
Code: [AUSKLAPPEN]
switch($action) {
  case 'get': getGames($table); break;
  case 'new': addGame($table, $ip, ...); break;
  ...
  default: echo '-- Unkown command';
}


Code: [AUSKLAPPEN]
    $abfrage = "SELECT * FROM $table WHERE ID = '$id' ";
    $ergebnis=mysql_query($abfrage);
    $err = mysql_error();
    if ($err != "") {
        return;
    }

1. Wie oben gesagt, Strings in ', nicht in ".
2. Variablenbezeichner mittels '...'.$var.'...'; bzw. "...{$var}..." einbinden.
3. Wenn das Query fehlerhaft ist, wird FALSE zurück gegeben. Es reicht folglich ein if($ergebnis === FALSE), um zu prüfen, ob das Query fehlerfrei war. Der Aufruf von mysql_error ist an dieser Stelle unnötig.

Code: [AUSKLAPPEN]
if ($ipString=="") { 

besser:
Code: [AUSKLAPPEN]
if(!strlen($ipString))
oder
if(empty($ipString))

Starwar

BeitragFr, Jun 25, 2010 22:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für deine konstruktive Kritik.
Ich muss zugeben, dass ich die " nur aus Gewohnheit genommen habe. Deshalb auch keine Switch-Blöcke (was in diesem Fall wirklich viel übersichtlicher gewesen wäre). Doctype. Nunja, das gehört für mich eben dazu.
Die Sache mit dem mysql_error() habe ich nachher hinzugefügt, da ist deine Lösung wesentlich eleganter. Danke dafür.
Öhmm, ja die ' bei $table. Die habe ich einfach vergessen... Rolling Eyes
Die groß/kleinschreibung Englisch/Deutsch hat durchaus ein System. Damit kann man Zähl/Temp/Langlebige Variablen unterscheiden. die Unterstriche stellen Ebenen dar.
Genug der Rechtfertigungen.
Ich werde bei Gelegenheit den Code ein wenig säubern. Ich hoffe ich kann trotzdem (auch dir) ein wenig Arbeit abnehmen und einen guten Einstiegspunkt gegen.
So weit, MFG.

EDIT: Kennst du ein gutes PHP-Tutorial? Also eins in dem man auch ordentliche Verwaltung, casts, etc. erklärt bekommt. Du siehst, ich habe in PHP mehr Halbwissen als Erfahrung.

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group