Sockets

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

Firstdeathmaker

Betreff: Sockets

BeitragFr, Jun 16, 2006 18:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Kann mir jemand ein mini-Beispiel geben wie das mit den Sockets funktioniert?
Also einfach einen Server, der dann von einem Client eine Nachricht empfängt.
Ich krieg einfach nirgendwo eine Info her wie das geht (Und auch das rumprobieren hat bisher nicht zum erfolg geführt).
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Jolinah

BeitragFr, Jun 16, 2006 22:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Code: [AUSKLAPPEN]
Local socket:TSocket = Null
Local tcp:TSocketStream = Null

socket = CreateTCPSocket()
If socket <> Null
   If BindSocket(socket, port)
      SocketListen(socket)
      'Stream Objekt aus dem Socket erstellen
      tcp = CreateSocketStream(socket, True)
   EndIf
EndIf


Erst wird ein Socket erstellt, dieses wird für einen Server an den lokalen Port gebunden und wird dann in den Listening Modus versetzt. Aus dem Socket lässt sich dann ein Stream-Objekt erstellen. Mit dem kann man ganz normal die Read/Write Befehle wie bei BB benutzen:

Code: [AUSKLAPPEN]
WriteByte(tcp, 20)


Zum verbinden funktioniert es beinahe identisch, nur wird statt SocketListen() die Funktion ConnectSocket() verwendet.

Firstdeathmaker

BeitragFr, Jun 16, 2006 23:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Aha, vielen Dank! Fast soweit war ich auch schon mit meinen Überlegungen, nur fehlte mir das Wissen wie es mit dem Listen zu realisieren wäre, ob man das vielleicht eben jeden Schleifendurchgang abfragen müsste oder so, was ja nicht der Fall zu sein scheint. Nur jetzt ist ein Fehler aufgetaucht, den ich immer noch nicht zu lösen vermag. Ich hab nun einen Server und einen Client. Der Server wird zuerst gestartet und soll nun alles ausgeben was er empfängt. Damit er nicht zuviel Last zieht hab ich mal ein Delay 10 eingebaut. Nun starte ich den Client, welcher dem Server einen String schicken soll (Also eine einzige Zeile). Sobald ich den Client nun aber starte, bekommt der Server eine Fehlermeldung genau an der Stelle wo er die Nachricht printen müsste, in der Zeile
Zitat:
Print ReadLine (tcp)

wo ich eine Unhandled Exception bekomme, also "Attempt to access field or method of Null object". Das komische ist jedoch, dass ich nirgentwo ein solches nicht verbundenes Objekt entdecken kann im Debugger. oder liegt es einfach daran, dass ich versuche vom Client aus eine Verbindung mit der Server auf dem gleichen PC herzustellen und man das nicht darf?

Zum Nachvollziehen (und vielleicht testen), mein Code sieht folgendermaßen aus:

Server
Code: [AUSKLAPPEN]
Local socket:TSocket = Null
Local tcp:TSocketStream = Null

Local port:Int = 120

socket = CreateTCPSocket()
If socket <> Null
   If BindSocket(socket, port)
      SocketListen(socket)
      'Stream Objekt aus dem Socket erstellen
      tcp = CreateSocketStream(socket, True)
   EndIf
EndIf




Repeat
   If Eof(tcp) <> 0
      Print ReadLine (tcp)
   EndIf
   Delay 10
Until KeyHit(KEY_ESCAPE)
End


Client
Code: [AUSKLAPPEN]
Local socket:TSocket = Null
Local tcp:TSocketStream = Null

Local port:Int = 190

socket = CreateTCPSocket()
If socket <> Null
   If BindSocket(socket, port)
      ConnectSocket(socket, ipint("127.0.0.1"), 120)
      'Stream Objekt aus dem Socket erstellen
      tcp = CreateSocketStream(socket, True)
   EndIf
Else
   Print "Could not create socket"
EndIf


WriteLine (tcp, "Hello")

End


Function ipint:Int(umwandeln$)
   Local teil1:Int = Int(Instr(umwandeln$,"."))
   Local teil2:Int = Int(Instr(umwandeln$,".",teil1+1))
   Local teil3:Int = Int(Instr(umwandeln$,".",teil2+1))
   Local temp1:Int = Int(Mid(umwandeln$,1,teil1-1))
   Local temp2:Int = Int(Mid(umwandeln$,teil1+1,teil2-1))
   Local temp3:Int = Int(Mid(umwandeln$,teil2+1,teil3-1))
   Local temp4:Int = Int(Mid(umwandeln$,teil3+1))
   zurueck:Int = (temp1 Shl 24) + (temp2 Shl 16) + (temp3 Shl 8) + temp4
   Return zurueck
End Function
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Jolinah

BeitragSo, Jun 18, 2006 12:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Bin mir nicht mehr ganz sicher ob Bindsocket beim Client auch nötig ist. Wahrscheinlich sucht der sich automatisch einen lokalen Port. Aber ich glaube daran liegts nicht..

Versuch statt Eof(tcp) mal tcp.Socket().ReadAvail() > 0, vielleicht bringt das was. Oder evtl. hilft es das TCP Delay umzustellen:

Code: [AUSKLAPPEN]
socket = CreateTCPSocket()
If socket <> Null
   If BindSocket(socket, port)
      SocketListen(socket)
      socket.SetTCPNoDelay(True) <------------------ Hier
      'Stream Objekt aus dem Socket erstellen
      tcp = CreateSocketStream(socket, True)
   EndIf
EndIf


Ansonsten weiss ich auch nicht.. vielleicht ist der Fehler auch im BMax Modul selber..

Firstdeathmaker

BeitragSo, Jun 18, 2006 12:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Nee, hat leider alles nix gebracht. Aber trotzdem danke für deine Mühe!
Ich werd die Frage mal im englischen Board stellen, vielleicht wissen die ja eine Lösung...


Edit: Hab da was gefunden
http://www.blitzbasic.com/Comm...847#643388

Firstdeathmaker

BeitragSo, Jun 18, 2006 14:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Hab das ganze mal auseinandergefummelt, für alle die es interessiert ein kleines Beispiel:

Server
Wichtig: Man hat einen Hauptsocket im Listen Modus, auf dem man nach Verbindungsanfragen lauscht. Wenn eine Anfrage kommt, wird diese mit einem NEUEN Socket verbunden und von dem aus wird ein Stream erstellt aus dem man die Daten auslesen kann. Komischerweise muss man in die Listenschleife wo nach neuen Connections gelauscht wird ein delay einbauen, sonst funktioniert das nicht (Jedenfalls nicht an einem PC, an zwei hab ich jetzt nicht getestet). Später braucht man nur noch auf den einen Stream den man erstellt hat zuzugreifen.

Code: [AUSKLAPPEN]
SuperStrict


Global MainSocket:TSocket = CreateTCPSocket()
BindSocket(MainSocket, 666)
SocketListen(MainSocket)

Local receivesocket:TSocket
Local IncomingStream:TStream

Repeat
   receivesocket:TSocket = SocketAccept(MainSocket)
   IncomingStream:TStream = CreateSocketStream(receivesocket)
   Delay 10
Until receivesocket <> Null

Print "Incoming..."

Repeat
   If IncomingStream <> Null
      While Not Eof(IncomingStream)
         Local line:String = ReadLine(IncomingStream)
         If line <> "" Print line
      Wend
   EndIf   
Until KeyHit(KEY_ESCAPE)
End



Client
Der Client hat einen anderen Knackpunkt an dem ich fast verzweifelt bin: Man darf nicht zu früh anfangen etwas in den Stream zu schreiben, sonst gehen die Daten darin verloren. Deshalb das delay 100 bevor ich etwas in den Stream schreibe. Danach ist aber alles in Ordnung. Vielleicht könnte man das auch eleganter lösen indem man Abfragen einbaut, ob die Connection schon soweit ist, aber damit werde ich mich erst später beschäftigen. Ich bin froh das es jetzt erstmal so läuft Wink
Falls jmd Verbesserungen hat, immer her damit!
Code: [AUSKLAPPEN]
SuperStrict


Global SendSocket:TSocket = CreateTCPSocket()
Global SendStream:TStream = CreateSocketStream(SendSocket)
ConnectSocket(SendSocket, HostIp("localhost"), 666)

Delay 100
WriteLine SendStream, "Hallo"


Delay 1000
WriteLine SendStream, "Zweiter Batzen"


End
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Jolinah

BeitragSo, Jun 18, 2006 18:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Achso, logisch Smile

Sorry hab nicht mehr daran gedacht, ist mir beim überfliegen deines Codes auch irgendwie nicht aufgefallen.. aber war bei TCP ja eigentlich schon immer so Wink
 

X0r

BeitragFr, Jul 21, 2006 0:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich weiß, das Thema ist schon längst gegessen, aber bei mir muss das Programm nicht stoppen(Kein delay benutzen), damit die Daten ankommen.
Ist zwar fast der selbe code aber hier ist meiner:

Server:
Code: [AUSKLAPPEN]

socket:Tsocket=CreateTCPSocket()

BindSocket socket,0
SocketListen(socket)

For Local ips=EachIn HostIps("")
ip=ips
Next


Print ip
Print SocketLocalPort(socket)


Repeat
   receivesocket:TSocket = SocketAccept(socket)
  stream:TStream = CreateSocketStream(receivesocket)

Until receivesocket <> Null



Repeat




If stream<>Null Then

While Not Eof(stream)
         Local line:String = ReadLine(stream)
     If line<>"" Then  Print line
      Wend
EndIf


Until KeyHit(1)






CloseSocket(socket)




Client
Code: [AUSKLAPPEN]

socket:Tsocket=CreateTCPSocket()

stream=CreateSocketStream(socket)
ConnectSocket(socket,ipint,port)







WriteLine Stream, "Hallo"

WriteLine Stream, "world!"


CloseSocket(socket)



Nachdem ihr Server gestartet habt, wird die IP als Integer Wert und der Port gezeigt. Dann startet das Client Programm und gibt bei ipint die zurückgegebene IP und bei port den zurückgebenen port ein.

Jolinah

BeitragFr, Jul 21, 2006 8:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Das Delay war nicht da um auf Daten zu warten, sondern um die CPU- Auslastung zu mindern. Bei Delay wird der Prozess unterbrochen, so dass Windows etwas mehr Zeit hat noch andere Dinge zu erledigen und dein Programm nicht 100% die CPU auslastet Wink
 

X0r

BeitragFr, Jul 21, 2006 10:17
Antworten mit Zitat
Benutzer-Profile anzeigen
>Der Client hat einen anderen Knackpunkt an dem ich fast verzweifelt bin: Man darf nicht zu früh anfangen etwas in den Stream zu schreiben, sonst gehen die Daten darin verloren. Deshalb das delay 100 bevor ich etwas in den Stream schreibe.

Und was sagst du dazu? du hattest FDM zugestimmt.

Und selbst wenn es mit 100% so wäre, der müsste trotzdem senden.

Und? Gibt es eine elegantere Lösung, um die Auslastung zu verhinden?
Ich habs schon mit socketconnected und so versucht, hat irgendwie alles nichts gebracht. Und es ist schon komisch, dass man extra ein delay am Ende der Schleife setzen muss, damit das CPU nicht crashed.
Ist zwar logisch, aber es muss doch eine bessere Lösung geben, oder?
Denn langsamere Computer brauchen dann doch mehr Zeit, oder wie ist das mit TCP streams?

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group