
Übersicht
Einleitung
1. Grundlagen
2. Variablen
3. Schleifen
4. Entscheidungen
5. Struktur
6. Eingabe
7. Gfx-Grundlagen
8. Bilder anzeigen
9. Kollision
10. Sound & Musik
11. Dateien
12. Multiplayer

Spiele
Grafik
Mathe
Netzwerk
String
Verschiedenes
|
Multiplayer & Netzwerk
© Robert Gerlach 2001-2002
www.robsite.de
Multiplayer- und Netzwerkzeug ist so ziemlich das schwerste und umfangreichste was es in BB gibt, daher
bin ich dem ganzen auch erfolgreich bis zum letzten Teil des Kurses ausgewichen ^_^.
Die paar BB-Befehle sind nicht sehr schwer zu verstehen, das Problem ist das Internet welches
recht komplex ist. In diesem Kurs kann ich mich deshalb nicht um alles kümmern sondern
nur um die wichtigsten Sachen wie z.B. DirectPlay, UDP, TCP, FTP, Mailversand u.s.w.
Mit diesem Grundwissen müsste man genug gewappnet sein um selbstständig weiterzuforschen, ob mit
BB oder ohne.
Und da ich selbst dummerweise kein Netzwerk zum ausprobieren zur Verfügung hab, meldet bitte alle Fehler die zufällig irgendwo
aufgetaucht sind...^_^
Nun denn, fangen wir an.
IP-Adressen, Ports und Protokolle
Das Internet ist ein Netz von sehr vielen Rechnern welche alle über mehr oder weniger schnelle
Leitungen verbunden sind. Jeder Rechner hat seine eigene IP-Adresse, seine Identität in Form einer
Zahlenkombination welche so aufgebaut ist: xxx.xxx.xxx.xxx wobei jedes xxx von 0 bis 255 (ein Byte) gehen kann. Das ergibt ~4 Mrd. Möglichkeiten, im Moment noch
genug für alle Computer... Hat man die IP-Adresse eines Rechners kann man eine Verbindung zu ihm über einen freien Port
(sozusagen eine "Tür") aufbauen. Einige Ports sind fest belegt mit verschiedenen Protokollen, andere kann man individuell nutzen.
Wären aber alle Ports frei zugänglich (wie sie es auch oft bei ungeschützten Computern sind), können Programme somit recht einfach
eine Verbindung zu diesem Computer aufbauen und Verschiedenes drauf machen, Trojaner sind ein
gutes Beispiel. Um das zu vermeiden gibt es Firewalls, die einfach nur die Ports sperren und nur
ausgewählten Programmen den Datentransfer erlauben.
Ruft man bei sich zuhause nun eine Datei von irgendeinem Server auf der
Welt ab, wird diese Anfrage über eine Menge anderer Rechner zum Ziel-Server geleitet welcher
dann das Angeforderte auf die Reise zurück schickt. Dazu werden Protokolle eingesetzt die das ganze
regeln, also dafür sorgen dass die Daten über die verschiedenen Server bei einem vollständig ankommen.
Das verbreitetste ist das TCP Protokoll, welches man auch in Blitz Basic nutzen kann.
Es wurde dafür geschaffen um Daten ohne Verlust auch nur eines Bits zum Empfänger zu transportieren.
Dazu werden zu große Dateien in einzelne Pakete aufgeteilt und solange an den Empfänger geschickt bis
alles perfekt angekommen ist.
Das ist eigentlich gut, denn der kleinste Fehler kann eine Datei unbrauchbar machen, aber auch wieder schlecht,
weil die einzelnen Pakete dadurch sehr groß werden (der Header eines TCP-Pakets ist 22 Bytes groß...).
Darum wird das TCP Protokoll in Spielen so gut wie nie eingesetzt, denn dort kommt es nicht unbedingt
auf perfekte Daten sondern auf Geschwindigkeit an.
Genau dafür wurde das User Datagramm Protocol, kurz UDP geschaffen.
Der Header ist zwar kleiner (8 Bytes), dafür kann man aber nicht sicher gehn dass alle Daten
ankommen. Geschwindigkeit auf Kosten der Zuverlässigkeit. Da ein paar fehlende Daten bei
Actionspielen aber nicht weiter auffallen wird bei Spielen meist UDP eingesetzt.
Dann gibt es noch DirectPlay. Es ist kein eigenes Netzwerkprotokoll sondern einfach nur ein
Aufsatz (Ein Messaging (Nachrichten) Protokoll) über normale Netzwerkprotokolle (TCP/IP, IPX etc).
Man braucht sich also nicht darum zu kümmern wie der andere User verbunden ist, man kann
einfach seine Messages rüberschicken und hat sonst nichts tiefergehendes zu tun.
Fangen wir also erstmal mit DirectPlay an, denn das ist das einfachste...
DirectPlay
Eine DirectPlay Session (Sitzung) ist ein Verbund von verschiedenen Programmen die alle
untereinander kommunizieren können. Will eines mit einem anderen kommunizieren, müssen beide in der gleichen Session sein. Ein Programm kann
entweder einer bereits bestehenden Session beitreten oder eine neue eröffnen und auf Teilnehmer warten.
Das Programm welches die Session startet ist der Host, er leitet die Session.
Standardmäßig ist in DirectPlay der Peer-to-Peer Modus eingestellt, was heisst dass der aktuelle Status der Session
an jeden einzelnen Computer geschickt wird. Jeder ist also mit jedem verbunden. Das andere Modell wäre eine
Client/Server Architektur wo ein Client seine Daten an den Server schickt welcher diese dann an die anderen Clients
weiterleitet. Blitz Basic nutzt meines Wissens nach die Standardeinstellung, also Peer-to-Peer (P2P).
Ein kleines Beispiel:
 |
|
 |
Peer-to-Peer |
|
Client/Server |
Um Messages (Daten) empfangen und senden zu können muss das Programm einen Spieler erstellen. Messages
werden immer zu Spielern geschickt, nicht zu Computern (da theoretisch mehrere Spieler auf einem
Computer existieren können). Spieler werden in zwei Gruppen eingeteilt. Local und Remote. Lokale
Spieler befinden sich auf dem eigenen Computer, Remote-Spieler auf anderen.
Ok, starten wir ein Spiel.
Starten wir dieses Ein-Zeilen-Programm bekommen wir folgendes zu sehn:

Wählen wir nun eine der drei Möglichkeiten für Verbindungen, kommt ein kleiner Dialog
in dem man die IP-Adresse des Hosts eingeben kann:

Das ganze ist recht einfach, hat nur den Nachteil dass sich das BB-Programm minimiert
um dem Dialog Platz zu machen. Danach wird zwar automatisch wieder zum Programm zurückgekehrt,
es ist aber immernoch eine Unterbrechung... Dazu gibt es zwei andere Kommandos:
spiel = HostNetGame("Name
des Spiels")
; und
spiel = JoinNetGame("Name
des Spiels", Host_IP$) |
Mit HostNetGame hostet man also ein Spiel, mit JoinNetGame tritt man einem
bestehenden Spiel bei. Hat alles geklappt liefern beide eine 2 zurück, wenn nicht,
eine 0 oder 1.
In unserem Fall hat jetzt alles geklappt und wir befinden uns mit mehreren anderen Spielern in
einer Session. Nun müssen wir nur noch einen Spieler erschaffen, durch den wir dann Messages
verschicken können:
spieler = CreateNetPlayer("Name
des Spielers")
|
Hat spieler den Wert 0 hat irgendwas nicht funktioniert und wir sind nicht
im Spiel... Andernfalls wird die Identität des Spielers als Nummer zurückgeliefert.
Nun ist man im Spiel und kann Nachrichten empfangen/versenden. Alle an einen
gesendeten Nachrichten kommen erstmal in eine Schlange und werden nach und nach abgearbeitet.
Um zu prüfen ob man eine Nachricht bekommen hat nehme man:
var hat den Wert 1 wenn eine Nachricht empfangen wurde und 0 wenn nicht.
Wurde eine empfangen, kann man recht viel mit ihr machen. Zum Beispiel erstmal rausbekommen
was für eine Nachricht das überhaupt ist:
Ist nachricht eine Zahl von 1 bis 99 kommt die Nachricht von einem Spieler.
Andere Nummern haben andere Bedeutungen:
1-99 - Nachrichten von anderen Spielern
100 - Ein neuer Spieler ist der Netzwerksession beigetreten
101 - Ein Spieler hat die Session verlassen
102 - Der Host hat die Session verlassen und der eigene Computer ist nun Host
200 - Ein Problem ist aufgetreten und die Session muß beendet werden
|
Nehmen wir also an, ein Spieler hat uns irgendwas geschickt. Um die Identität des Spielers (seine Nummer)
zu kriegen nehme man:
spieler_nummer = NetMsgFrom()
|
Ganz praktisch wenn man weiss dass die empfangene Nachricht nur von einem Spieler kommen kann.
Hat man zudem noch das Bedürfnis den Spielernamen zu kennen nehme man NetPlayerName$():
spieler_name$ = NetPlayerName$(spieler_nummer)
|
Jetzt das wichtigste, die Nachricht selbst ^_^. Ihren Inhalt kann man in eine Variable
speichern:
nachricht$ = NetMsgData$()
|
Diese kann man nun auswerten, also sein Programm durch sie verändern (wenn es eine Spielerposition
ist den Spieler an die neuen Kordinaten setzen etc.) und dann auch irgendwann selbst
eine Nachricht mit seinen aktualisierten Daten verschicken:
SendNetMsg code, nachricht$,
sender_nummer, empfaenger_nummer [,wichtig]
|
code kann nur eine Nummer von 1 bis 99 sein, nachricht$ ist die Nachricht selbst als
ASCII-Text, die sender_nummer ist die eigene (welche man mit CreateNetPlayer() geliefert
bekommt) und empfaenger_nummer ist die Nummer des Empfängers... Das optionale wichtig (1 oder 0)
gibt an ob eine Nachricht unbedingt am Ziel ankommen muss (wie die TCP-Pakete). Dadurch wird
sie aber auch ca. 3 mal langsamer übermittelt. Ist also nur in Ausnahmesituationen zu empfehlen...
Nun können wir einer Session beitreten/eine neue eröffnen, Nachrichten empfangen, auswerten und selbst
welche verschicken. Um am Ende die Verbindung zur Session zu trennen, gibt es StopNetGame:
Wie gesagt ist mit DirectPlay am einfachsten zu arbeiten wenn man nur Spiele vernetzen will. Es gibt aber
noch mehr, z.B. das UDP Protokoll:
UDP
UDP ist, wie oben schon erwähnt, weit besser für Spiele geeignet als TCP, da die Pakete sehr viel
kleiner sind. Von den BB-Befehlen ist es in etwa eine Mischung aus DirectPlay und TCP. Aber
fangen wir erstmal an...
Um einen Netzwerk-Stream zu erschaffen gibt es CreateUDPStream(), er liefert
einen Wert für den eben eingerichtetetn Daten-Stream zurück:
udp_stream = CreateUDPStream([portnummer])
|
Einen Port sollte man (optional) angeben, macht man es nicht sucht BB automatisch nach einem freien.
Hat udp_stream den Wert 0 konnte keine Verbindung aufgebaut werden.
Streams hatten wir auch schonmal, nämlich im Datei-Tutorial.
Alles was wir jetzt mit den Read und Write Befehlen in einen Sende-Stream schreiben, können
wir dann per UDP-Protokoll versenden. Empfangene Nachrichten kommen dagegen in einen eigenen Stream, den
Empfangs-Stream. Man braucht also zwei Streams, denn wenn man nur einen hätte und in ihn eine
Nachricht zum versenden schreibt aber gleichzeitig eine Fremdnachricht eintrifft würden wir ja
unsere eigene und die Fremadnachricht verschicken. Nicht gut...
Der Übersichtlichkeit halber sollte man in seinem Programm am besten auch den Port direkt mit
angeben damit es nicht zu Verwechslungen kommt und generell einfacher wird ^_^.
Gut, erstellen wir also erstmal einen Stream auf Port 8000 zum Nachrichten empfangen:
empfangs_stream = CreateUDPStream(8000)
|
Nun können wir neue Nachrichten empfangen (vorausgesetzt der Sender hat die Daten an diesen Port geschickt), dies geht mit RecvUdpMsg:
IP_Adresse = RecvUdpMsg(empfangs_stream)
|
Wurde eine Nachricht empfangen, hat IP_Adresse den Integer-Wert der IP-Adresse des Senders, wurde
keine empfangen kommt eine 0 zurück. Integer-Wert heisst dass z.B. die IP-Adresse 99.13.113.29 als
23136661789 zurückkommt. In die besser lesbare Punktform kann man sie mit DottedIP() umwandeln:
IP_String$ = DottedIP(IP_Nummer)
|
Das aber nur nebenbei...
Nehmen wir also an jemand hat uns freundlicherweise eine Nachricht geschickt die nun im Empfangs-Stream darauf
wartet ausgelesen zu werden. Nun kommt der alte Read-Befehl zum Einsatz, mit dem wir auch schon
aus Datei-Streams gelesen haben:
byte = ReadByte(empfangs_stream)
|
Ein Byte haben wir jetzt aus dem angekommenen Stream rausgelesen, es sind aber vermutlich noch ein paar mehr drin. Wieviele
Bytes in einem Stream vorhanden sind können wir mit ReadAvail() rausbekommen:
gesamt_byte_anzahl = ReadAvail(empfangs_stream)
|
Ist gesamt_bytes_anzahl über 0 sind noch Bytes drin, wir können also noch welche auslesen.
Man kann auch einfach mit ReadLine den gesamten Stream auslesen, ist oft einfacher.
Jetzt wäre es aber erstmal angebracht die Nachricht auch zu beantworten. Dazu müssen wir
die IP des Senders und dessen Empfangsport kennen. Die IP ist kein Problem, die haben wir schon
mit RecvUdpMsg() bekommen, was noch fehlt ist der Port. Kommunizieren zwei gleiche Programme
miteinander (was bei Spielen eigentlich immer so ist), ist der Empfangsport immer der gleiche (hier 8000).
Nun haben wir eigentlich alles. Was noch fehlt ist ein Sendestream:
sende_stream = CreateUDPStream(8001)
|
Perfekt. Nun können wir mit Write Nachrichten in den Stream schreiben und mit
SendUdpMsg den gesamten Stream übertragen. Nun denn, ans Werk:
WriteLine(sende_stream,
"Bedeutende Nachricht") ;
Beliebiges Zeug in den Stream schreiben
SendUdpMsg sende_stream, IP_Adresse, [port]
; Den ganzen Batzen auf einmal senden. |
Wieder ist ein optionales port dabei, für den Fall dass man nicht über den normalen Sendeport
sondern irgendeinen anderen senden will. Kann also eigentlich weggelassen werden.
Das wären die Grundlagen der UDP-Kommunikation. Einen Sende- und einen Empfangs-Stream erstellen, abfragen
ob auf dem Empfangsport eine Nachricht eingegangen ist, wenn ja diese auslesen und dann in den
Sendestream einen Nachricht schreiben und diese verschicken. Alle Befehle nochmal in logischer
Reihenfolge™:
; Die Streams erstellen
sende_stream = CreateUDPStream(8001)
empfangs_stream = CreateUDPStream(8000)
; Eine Nachricht empfangen
IP_Adresse = RecvUdpMsg(empfangs_stream)
; Wenn einen Nachricht empfangen wurde ein Byte auslesen
If IP_Adresse <> 0
Then byte = ReadByte(empfangs_stream)
; Ein Byte in den Sendestream schreiben
WriteByte(sende_stream, 23)
; Den Stream an die IP Adresse und den Port desjenigen
senden von dem man die Nachricht empfangen hat
SendUdpMsg sende_stream, IP_Adresse |
Das ganze ist also schon etwas anders als DirectPlay wo man die Nachricht direkt verschickt und nicht erst
in einen Stream schreibt. Die dritte Möglichkeit ist TCP, dort kann man direkt mit Read
und Write Daten senden und empfangen.
TCP
Wie oben schon erwähnt ist das TCP-Protokoll eher weniger für schnelle Spiele geeignet. Ein
Datenpaket muss hier nämlich unbedingt vollständig am Ziel ankommen, tut es das nicht wird
es nochmmal geschickt. Das kostet Zeit..., ist aber egal wenn man z.B. eine Datei
von einem Server holen oder eine Mail verschicken will.
Öffne wir also einen direkten Stream zu einem Server:
stream = OpenTCPStream("www.robsite.de",
port [,eigener Port])
|
Das wichtigste daran ist der Port, also das Protokoll mit dem man arbeiten will. Eine
Liste mit Ports gibt es hier.
Man kann aber nicht alle diese Ports bei jedem Rechner ansprechen. Bei einem nicht-Mailserver z.B.
wird es recht schwer sein eine POP3 (Mailprotokoll) Verbindung aufzubauen u.ä.
Den Port über den man selbst sendet kann man auch noch angeben, ist aber eigentlich egal.
Nehmen wir uns erstmal FTP (File Transfer Protocol, Port 21) vor. Es ist das Standard-Protokoll zur verlustfreien
Datenübertragung und auch etwas schneller als HTTP (Hyper Text Transfer Protocol, Port 80). Hat
man zufällig selbst irgendwo etwas Webspace und einen FTP-Zugang, kann man mit einem FTP-Client (LeechFTP, CuteFTP, ...)
darauf zugreifen, Daten runter- und hochladen und die Verzeichnisse verwalten/erstellen/löschen u.s.w.
Alles was diese FTP-Programme machen ist, eine (grafische) Oberfläche über die einzelnen FTP-Befehle
zu legen und somit das ganze zu vereinfachen. Kommandozeilenjunkies können auch 'ftp' in der MS-DOS-Eingabeaufforderung
eingeben und kommen zum textbasierten Windows-FTP-Client.
Da dies hier aber kein großes FTP-Kompendium werden soll nur ein kleiner Überblick und ein kleines Programm
mit dem man etwas experimentieren kann:
server$ = Input("Adresse>")
; Die Adresse eingeben (IP-Adresse oder z.B. robsite.de)
stream = OpenTCPStream(server$, 21)
; Die Verbindung zum Server auf Port 21 herstellen.
; Die Input/Output-Schleife
Repeat
; Alles was der Server einem schickt auslesen und
printen.
l$ = ReadLine$(stream)
Print l$
; Kommandos eingeben lassen und selbige an den Server
schicken.
i$ = Input(">")
WriteLine stream, i$
; Solange wiederholen bis man 'ende' eingibt.
Until i$ = "ende"
End
|
Startet man es jetzt, kann man als erstes die Adresse des Rechners eingeben mit dem man verbunden werden
will. Nach einer kurzen Wartezeit liefert er einen FTP-Antwort-Code zurück. Es gibt viele Antwort-Codes,
genauso wie z.B. beim HTTP-Protokoll. Dort bedeutet z.B. 404 dass eine Seite nicht gefunden wurde und 200
wenn alles OK ist. Der OK-Code beim FTP ist 220. Sieht man jetzt auf dem Bildschirm also eine 220 gefolgt
von einem kleinen Text (z.B. "FTP Server Ready") kann man weitermachen, nämlich mit der Anmeldung.
Dazu muss man den Usernamen und das Passwort für den Server kennen. Hat man sich eingeloggt kann
man dann Daten verschicken, empfangen, in Verzeichnissen stöbern etc. Dies ist aber recht kompliziert, daher
empfehle ich die RFCs, die Request for Comments Datenbank
in der seit 1969 alle Beschreibungen von Standards festgehalten sind. Inzwischen gibt es über 3231 davon...
FTP wird in Nummer 114 (und sehr vielen anderen) beschrieben. Ein sehr kurzer Beispieldialog einer FTP-Session:
I = Ich
S = Der Server
I: Adresse>robsite.de
S: 220 FTP Server Ready
I: USER xyxyxy
S: 331 Password required for xyxyxy
I: PASS xyxyxy
S: 230 User xyxyxy logged in.
I: HELP
S: 214-The following commands are recognized (* =>'s)
I: [Enter]
S: USER PASS ACCT* CWD XCWD CDUP XCUP SMNT*
I: [Enter]
S: QUIT REIN* PORT PASV TYPE STRU MODE RETR
I: quit
|
So ungefähr läuft es ab. Einen recht guten FTP-Client in Blitz Basic geschrieben (von Mark Sibly selbst)
gibt es hier. Die puren FTP-Kommandos sind recht schwer und umständlich
anzuwenden, jedenfalls hab ich es noch nicht so richtig geschafft eine Datei von robsite.de runterzuladen ^_^.
Da kann man nur froh sein dass es inzwischen fertige FTP-Clients gibt...
Für Spiele ist FTP nicht sehr wichtig, man könnte aber z.B. (automatisch) neue Level oder Patches
runterladen, den ersten FTP-Client schreiben der DirectX benötigt u.s.w. ^_^
Nun noch eine andere Anwendungsmöglichkeit der TCP-Befehle: E-Mails. Die Mailprotokolle sind
etwas einfacher zu handhaben als FTP, dafür gibt es aber dummerweise drei verschiedene, eins fürs Senden, eins
zum empfangen noch eines das beides kann. Grob erklärt...
Um es konkreter zu sagen, zum empfangen nimmt man normalerweise POP3 (Post Office Protocol, Version 3), zum
versenden SMTP (Simple Mail Transfer Protocol). Das dritte Protokoll ist IMAP
(Internet Message Access Protocol), würde jetzt aber nur zur Verwirrung beitragen ^_^. POP3 reicht erstmal aus.
Gut, empfangen wir Mails. Besser gesagt, rufen wir Mails ab die von unserem Mailserver empfangen wurden und nun
dort rumlungern.
Ich gehe dabei mal von meinem web.de Account aus (robscure@web.de), denn
dieser unterstützt POP3 und SMTP.
Über Port 110 können wir nun eine POP3-TCP-Verbindung zum Mailserver aufbauen welcher mit einer Begrüßung antwortet.
Einfach das obere kleine Programm nehmen und die 21 durch eine 110 austauschen. Dann als Adresse
z.B. "pop3.web.de" eingeben und die Begrüßung abwarten.
Ist sie angekommen geht es weiter. Man durchläuft wärend der POP-Session 3 "States". Der erste ist
der "Authorization State", man meldet sich mit Username und Passwort an.
Danach kommt man in den "Transaction State", in dem man alle Aktionen wie Mails abrufen/löschen ausführen kann.
Diese werden aber nicht gleich vom Server ausgeführt. Erst nachdem man "quit" eingibt beendet der Server
die Verbindung und führt die Veränderungen durch ("Update State").
Es gibt auch eine Zeitbegrenzung, die standardmäßig auf mindestens
10 Minuten eingestellt ist. Jedes Kommando des Benutzers setzt den Zähler zurück, überschreitet man die 10 Minuten (oder mehr)
beendet der Server die Verbindung ohne die Änderungen auszuführen.
Nun denn, hier eine kleine Auflistung der möglichen Kommandos. Es sind nicht viele...
STAT - Liefert die Anzahl der gespeicherten Mails und ihre größe in Oktetts zurück
LIST [nummer] - Liefert die Nummer und Oktett-Größe aller Mails zurück. Wird dahinter noch eine Mail-Nummer angegeben, wird nur die Größe dieser Mail ausgegeben.
RETR nummer - Gibt die Mail mit der angegebenen Nummer aus.
DELE nummer - Löscht die Mail mit der angegebenen Nummer.
NOOP - Macht nichts, hält die Verbindung aufrecht um Time-Outs zu vermeiden.
RSET - Setzt die aktive Verbindung zurück. Noch nicht ausgeführte Änderungen werden verworfen.
|
Auf jedes Kommando antwortet der Server entweder mit +OK oder mit -ERR (und einem kleinen Text dahinter).
Das wars, mehr nicht. Schön einfach eigentlich ^_^. Hier nun ein kleiner Beispieldialog mit
einem POP3 Server über mein kleines Programm oben
(die Antworten des Servers müssen nicht unbedingt mit dem deines Maildienstes übereinstimmen, jeder ist anders...).
I = Ich
S = Server
I: Adresse>pop3.web.de
S: +OK WEB.DE POP3-Server
I: USER username
S: +OK Bitte Kennwort eingeben/enter password
I: PASS xyxyxy
S: +OK Postfach bereit/mailbox locked and ready
I: LIST
S: +OK 2 messages (320 octets)
I: [Enter]
S: 1 120
I: [Enter]
S: 2 200
I: [Enter]
S: .
I: RETR 1
S: +OK 120 octets
I: [Enter]
S: <Server sendet Nachricht 1>
I: [Enter]
S: .
I: DELE 1
S: +OK message 1 deleted
I: RETR 2
S: +OK 200 octets
I: [Enter]
S: <Server sendet Nachricht 2>
I: [Enter]
S: .
I: DELE 2
S: +OK message 2 deleted
I: RETR 3
S: -ERR no such message
I: QUIT
S: +OK
|
Für weitere POP-Infos: RFC Nr. 1725
Fein. Nun versenden wir noch eine Nachricht.
Zum versenden muss man sich nicht mit Username und Passwort beim Server anmelden, es geht auch so.
Normalerweise starten wir ein EMail-Programm welches dann mit dem MTA (Mail Transfer Agent, z.B. Sendmail) auf
dem Server kommuniziert. In diesem Fall machen wir dieses selbst.
Als erstes wieder das Programm oben nehmen und den Port in 25 ändern, es ausführen und z.B. "smtp.web.de" eingeben.
Darauf müsste eine Begrüßung folgen und man muss sich identifizieren (nicht anmelden sondern einfach nur "Hallo, ich bin xyz" sagen).
Dann gehts weiter mit dem verschicken der Mail, hier aber erstmal die 8 Standardbefehle die mindestens
zur Verfügung stehen:
HELO Emu - Identifizierung des Clients am Server mit Übergabe einer Adresse oder des Rechnernames (also irgendwas)
MAIL - Startet eine Mailübertragung. Als Argument wird die Absenderadresse ("From: karl@web.de") übergeben.
RCPT - Recipient. Identifiziert den Empfänger einer Mail. Bei mehreren Empfängern wird das Kommando einfach mehrmals ausgeführt.
DATA - Der Server antwortet mit 354 und wartet auf Eingabe der Nachricht.
RSET - Reset. Die Mailtransaktion wird abgebrochen. Die Verbindung zwischen beiden Rechnern bleibt aber bestehen.
VRFY - Verify. Überprüft eine Empfängeradresse auf Gültigkeit.
EXPN - Bei den meisten MTAs dasselbe wie VRFY.
NOOP - Dient zur Aufrechterhaltung der Verbindung, ohne dass es einen Time-Out gibt.
QUIT - Beendet die Verbindung. Der Server müsste daraufhin die Antwort "250 OK" zurückliefern.
|
Und ein kleiner Beispieldialog in dem eine Mail an 2 verschiedene Empfänger verschickt wird (die Antworten
des Servers sind auch wieder verschieden). Bei manchen Servern muss man sich auch zuerst per POP3
anmelden um dann mit SMTP Mails verschicken zu können ("SMTP after POP")...:
I = Ich
S = Server
I: Adresse>smtp.web.de
S: 220 web.de SMTP server ready
I: HELO Rob
S: 250 Rob, freut mich dich zu sehn
I: MAIL From:<robscure@web.de>
S: 250 <robscure@web.de> Sender ok
I: RCPT To:<horst@test.de>
S: 250 <horst@test.de> Recipient ok
I: RCPT TO:<tom@test.de>
S: 250 <tom@test.de> Recipient ok
I: DATA
S: 354 Enter mail
I: Hallo Horst und Tom!
I: Beispiel für den Mail-Versand mit SMTP.
I: Wisst ihr was?
I: Ich aber.
I: Haha...
I: .
S: 250 Mail accepted
I: QUIT
S: 221 web.de delivering mail
|
Der einzelne Punkt ist immer das Ende der Nachricht, danach wird sie verschickt.
Das wärs dann auch schon mit den Mails. Das ganze kann manchmal recht nützlich sein, um z.B.
aus einem Spiel herraus Spielspezifische Mails zu empfangen oder... für einen 3D-Mail-Client
oder andere lustige Sachen. Die Grundlagen stehen hier, wie es weiter geht liegt ganz
allein in euren Händen ^_^.
Wer mehr wissen will findet in den RFCs 1892
und 1894 genug Infos.
Zum Abschluss noch kurz ein bisschen was über Multiplayer in Spielen und wie man schonend mit der
Bandbreite umgeht...
Nehmen wir mal an 8 Spieler spielen zusammen ein Actionspiel mit rumlaufenden Figuren. Jeder hat eine Standardverbindung (ein 56k Modem) und
versendet pro Hauptschleifendurchlauf 20 Bytes (und das ist schon sehr wenig) an jeden Spieler. Das macht 2800 Bytes oder 2.8 KiloBytes.
Nun nehmen wir noch an dass das Spiel mit 30 fps läuft, somit werden in einer Sekunde 84 KiloBytes
versendet. Etwas viel.
Was könnten wir da nun tun... Erstmal sollten wir nicht 30 Mal in der Sekunde die eigenen Daten verschicken
sondern nur dann wenn sich auch etwas verändert. Noch besser ist es dagegen nicht die Position selbst
zu senden sondern nur die Richtung und die Geschwindigkeit. Solange diese nicht durch eine Bewegung des Spielers
geändert wird kann jeder andere Computer die neuen Positionen ganz einfach errechnen und benötigt somit
keine Daten vom Spieler. Wir schicken also nicht gleichmäßig (syncron) unser Zeug rüber sondern
nur dann wenn sich wirklich etwas verändert (asyncron).
Hiermit hätten wir schon einen ganzen Batzen Bandbreite eingespart und auch noch etwas den Lag
entschärft. Der Lag ist böse, er ist die Zeit die ein Datenpaket von einem zum anderen
Computer braucht wenn diese Übertragungszeit (Latenz) sehr hoch ist (mehrere 100 Millisekunden).
Dadurch kommt es zu Rucklern und allgemeinen Verzögerungen. Die Übertragungszeit kann man
nicht beeinflussen, manche Rechner antworten schnell, andere haben eine Schneckenverbindung...
Ganz anders ist es bei Nicht-Action-Spielen, z.B. rundenbasierten Strategietiteln, Kartenspielen
etc. Dort kommt es eigentlich nur auf die fehlerfreie Übertragung der Daten an, man kann also auch
TCP nehmen oder mit DirectPlay und hoher Priorität die Daten verschicken. Hat man dagegen das Problem
Daten schnell und fehlerfrei zu versenden muss man sich was einfallen lassen ^_^.
Am besten aber Werte die sich nicht laufend ändern komplett Verschicken und nicht nur die Differenz
zwischen dem letzten Wert. Also wenn man noch 100 Liter Öl hat und davor 90 hatte, schickt man nicht die Differenz 10 sondern
100, um Fehler zu vermeiden falls der andere noch 80 bei sich hat und dann 10 addiert --> 10 zuwenig...
Zusammenfassung
; --- Allgemein ---
IP-Adresse: Eine 12-stellige Nummer in der Form xxx.xxx.xxx.xxx mit welcher jeder ans Internet angeschlossene Computer identifiziert werden kann.
Ports: Sozusagen "Türen" nach außen. Es gibt 65535 (von 0 bis 65536) davon, hier gibts eine Liste der wichtigsten: ports.txt
Protokolle: Sie regeln wie Daten über die verschiedenen Computer übertragen werden.
; --- DirectPlay ---
; Um ein Netzwerkspiel mit der Standard-Dialogbox zu starten:
spiel = StartNetGame()
; Ein Netzwerkspiel ohne die Dialogbox hosten:
spiel = HostNetGame("Name
des Spiels")
; Und einem existierenden beitreten:
spiel = JoinNetGame("Name
des Spielers", Host_IP§)
; Einen Spieler für die Session erschaffen:
spieler = CreateNetPlayer("Name
des Spiels")
; Eine Nachricht empfangen:
var = RecvNetMessage()
; Die Art der Nachricht rausbekommen:
nachricht = NetMsgType()
; Liefert die Nummer des Spielers der einem die Nachricht
geschickt hat:
spieler_nummer = NetMsgFrom()
; Gibt den Namen zur Spielernummer zurück:
spieler_name$ = NetPlayerName$(spieler_nummer)
; Die eigentliche Nachricht abrufen:
nachricht$ = NetMsgData$()
; Eine eigene Nachricht verschicken:
SendNetMsg code, nachricht$, sender_nummer,
empfaenger_nummer [,wichtig]
; Ein Netzwerkspiel beenden:
StopNetGame
; --- UDP ---
; Einen UDP-Stream erstellen.
udp_stream = CreateUDPStream([portnummer])
; Hat amn eine Nachricht empfangen wird die IP des Senders zurückgeliefert.
IP_Adresse = RecvUdpMsg(empfangs_stream)
; Die dezimale IP-Nummer in die Form xxx.xxx.xxx.xxx umwandeln:
IP_String$ = DottedIP(IP_Nummer)
; Ein Byte aus dem Empfangs-Stream lesen (näheres
dazu im Datei-Tutorial):
byte = ReadByte(empfangs_stream)
; Ein Byte in den Sende-Stream schreiben:
WriteLine(sende_stream, "Bedeutende
Nachricht")
; Den Sende-Stream senden:
SendUdpMsg sende_stream, IP_Adresse, [port]
; --- TCP ---
; Einen TCP-Stream zu einem Server hin öffnen:
stream = OpenTCPStream("www.robsite.de",
port [,eigener Port])
; Danach kann man dann mit Read und Write auf den
Stream zugreifen. Der Port entscheidet über das Protokoll.
; --- Optimierung in Spielen ---
; Keine unnötigen Daten übertragen, nicht immer alles übertragen und von
der kleinsten
; verfügbaren Verbindung ausgehen (56K- oder 33K-Modem).
; Wichtige Daten als Ganzes senden, keine Differenz oder ähnliches.
|
Das wars mit der kleinen Netzwerkeinführung. Es gibt noch sehr viel mehr zu sagen, für weitere Infos
dürchwühle man das Linkarchiv auf www.robsite.de oder die RFCs.
- Ende des Hauptkurses -
Druckversion
|
|