Rob´s BB-Kurs 2

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 Session Client/Server Session
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.


spiel = StartNetGame()


Starten wir dieses Ein-Zeilen-Programm bekommen wir folgendes zu sehn:

DirectPlay Auswahlbox



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:

DirectPlay IP-Eingabe



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 sine Schlange und werden nach und nach abgearbeitet. Um zu prüfen ob man eine Nachricht bekommen hat nehme man:


var = RecvNetMessage()


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:


nachricht = NetMsgType()


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:


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: www.robsite.de/bbkurs2/ports.txt.
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: ftp://ftp.isi.edu/in-notes/rfc1725.txt

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.

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.