TCP Frage

  • Hallo Liebe Autoit.de Community !

    Zu Später Stunde habe ich noch eine frage :) zu TCP weil ich gerade nicht so wirklich weiter komme :thumbdown:

    Ich wollte gerne einen kleine Online - Mode schreiben doch dieser will nicht so wirklich wie ich will der Client Empfängt Postion - Pakete vorm Sender diese Position - Pakete sollen gemalt werden per GDIPlus doch leider klappt das mit dem Empfangen nicht so wirklich ;(

    Der Crap-Source

    [autoit]


    #RequireAdmin
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <Misc.au3>
    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Form1", 373, 260, 192, 124)
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

    [/autoit][autoit][/autoit][autoit]

    Global $MainChar, $OnlineChar
    Global $MainHeight, $MainWidth
    Global $OnlineHeight, $OnlineWidth
    Global $Background
    Global $Main_X = 1, $Main_Y = 1, $Online_X = 20, $Online_Y = 20
    Global $hGrafik, $hBuffer, $hBitmap

    [/autoit][autoit][/autoit][autoit]

    _GDIPlus_Startup()
    $MainChar = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Bilder\bewegung_unten1.png")
    $OnlineChar = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Bilder\bewegung_unten1.png")
    $Background = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Bilder\bck.png")

    [/autoit][autoit][/autoit][autoit]

    $MainHeight = _GDIPlus_ImageGetHeight($MainChar)
    $MainWidth = _GDIPlus_ImageGetWidth($MainChar)

    [/autoit][autoit][/autoit][autoit]

    $OnlineHeight = _GDIPlus_ImageGetHeight($OnlineChar)
    $OnlineWidth = _GDIPlus_ImageGetWidth($OnlineChar)

    [/autoit][autoit][/autoit][autoit]

    $hGrafik = _GDIPlus_GraphicsCreateFromHWND($Form1)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(373, 260, $hGrafik)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case Else
    _Steuerung()
    _RecvPosition()
    _ReDraw($MainChar, $Main_X, $Main_Y, $MainWidth, $MainHeight, $OnlineChar, $Online_X, $Online_Y, $OnlineWidth, $OnlineHeight)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit]

    EndSwitch

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    WEnd

    [/autoit][autoit][/autoit][autoit]

    Func _Steuerung()
    Select
    Case _IsPressed(25)
    $Main_X -= 2
    Case _IsPressed(26)
    $Main_Y -= 2
    Case _IsPressed(27)
    $Main_X += 2
    Case _IsPressed(28)
    $Main_Y += 2
    EndSelect
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func _ReDraw($Obj, $X, $Y, $Width, $Height, $Obj_1, $X_1, $Y_1, $Width_1, $Height_1)
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Background, 0, 0, 373, 260)
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Obj, $X, $Y, $Width, $Height)
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Obj_1, $X_1, $Y_1, $Width_1, $Height_1)
    _GDIPlus_GraphicsDrawImage($hGrafik, $hBitmap, 0, 0)
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func _RecvPosition()
    Local $IP = "127.0.0.1", $Port = 2266
    Local $MainSocket, $AcceptSocket, $RecvData, $DataSplit

    [/autoit][autoit][/autoit][autoit]

    TCPStartup()
    $MainSocket = TCPListen($IP, $Port)
    Do
    $AcceptSocket = TCPAccept($MainSocket)
    Until $AcceptSocket <> -1

    [/autoit][autoit][/autoit][autoit]

    $RecvData = TCPRecv($AcceptSocket, 1000)
    $DataSplit = StringSplit($RecvData, ";")
    If $DataSplit[0] == 2 Then
    $Onlin_X = $DataSplit[1]
    $Online_Y = $DataSplit[2]
    EndIf
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func _Exit()
    TCPShutdown()
    EndFunc

    [/autoit]

    Die _Exit Funktion ist nicht fertig wie man sieht aber dies sollte nicht mein Problem sein :evil: hat vlt jemand eine Idee ? warum das nicht will :?:

    Einmal editiert, zuletzt von Memory (26. August 2012 um 22:38)

  • Senden tuhe ich das

    [autoit]


    HotKeySet("{F1}", "_Sending")

    [/autoit][autoit][/autoit][autoit]

    Func _Sending()
    TCPStartup() ; TCP wird initialisiert

    [/autoit][autoit][/autoit][autoit]

    $socket = TCPConnect("127.0.0.1", 2266) ; Versucht eine Verbindung zum Server aufzubauen und speichert die SocketID in "$socket" ab

    [/autoit][autoit][/autoit][autoit]

    If $socket = -1 Then ; Wenn $socket = -1 ist, Fehlermeldung ausgeben
    MsgBox(16, "Error", "Die Verbindung zum Server konnte nicht hergestellt werden!") ; Fehlermeldung
    EndIf
    $Pos = Random(5, 134, 1)
    $Pos1 = Random(10, 370, 1)
    $sendedBytes = TCPSend($socket, $Pos & ";" & $Pos1) ; Sendet den Text an unseren verbundenen Socket

    [/autoit][autoit][/autoit][autoit]

    If $sendedBytes = 0 Then ; Wenn der Rückgabewert von TCPSend(...) 0 ist, Fehlermeldung ausgeben
    MsgBox(16, "Error", "Das Paket konnte nicht gesendet werden.") ; Fehlermeldung
    EndIf

    [/autoit][autoit][/autoit][autoit]

    TCPCloseSocket($socket)
    TCPShutdown()
    EndFunc ;==>_Sending

    [/autoit][autoit][/autoit][autoit]

    While 1
    Sleep(300)
    WEnd

    [/autoit]
  • Das Problem liegt wahrscheinlich darin, dass du in _RecvPosition() TCP und den Server jedes mal neustartest, und _RecvPosition() in einer Endlosschleife aufgerufen wird. Der Server ist zwar allgemein nicht optimal gelöst, aber TCPStartup und TCPListen an den Anfang des Skriptes zu verlagern sollte für den Anfang reichen.

    Für Spiele (besonders, wenn es dann mehrere Clients sind), würde ich dir UDP empfehlen. Das würde den Server (und auch die Clients) enorm vereinfachen.

    MfG, James

  • Danke erstmal !

    Ich habe mein Skript jetzt auf UDP abgestimmt doch leider klappt dies auch nicht gerade so ;( vlt könnt ihr euch es mal anschauen

    Client~

    [autoit]


    #RequireAdmin
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <Misc.au3>

    [/autoit][autoit][/autoit][autoit]

    HotKeySet("{ESC}", "_Exit")

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    #Region Die Form
    $Form1 = GUICreate("Online-Mode(Main)", 331, 245, 192, 124)
    GUISetState(@SW_SHOW)
    #EndRegion Die Form

    [/autoit][autoit][/autoit][autoit]

    Global $hMainChar, $hOnlineChar, $hBuffer, $hGrafik, $hBitmap, $hBackground
    Global $iMainChar_X = 2, $iMainChar_Y = 2, $iOnlineChar_X = 20, $iOnlineChar_Y = 20
    Global $iMainChar_Width, $iMainChar_Height, $iOnlineChar_Width, $iOnlineChar_Height
    Global $sIP = "127.0.0.1", $iPort = 2266
    Global $tMainSocket, $tBindSocket
    Global $aRecvData, $iTimeInit

    [/autoit][autoit][/autoit][autoit]

    UDPStartup()
    $tMainSocket = UDPOpen($sIP, $iPort)
    $tBindSocket = UDPBind($sIP, $iPort)
    UDPSend($tMainSocket, $sIP)
    $iTimeInit = TimerInit()
    Do
    $aRecvData = UDPRecv($tBindSocket, 2048)
    Until $aRecvData <> '' Or TimerDiff($iTimeInit) >= 5000

    [/autoit][autoit][/autoit][autoit]

    If TimerDiff($iTimeInit) >= 5000 Then Exit

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit]

    _GDIPlus_Startup()
    $hMainChar = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Bilder\bewegung_unten3.png")
    $hOnlineChar = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Bilder\bewegung_unten3.png")
    $hBackground = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Bilder\bck.png")

    [/autoit][autoit][/autoit][autoit]

    $iMainChar_Width = _GDIPlus_ImageGetWidth($hMainChar)
    $iOnlineChar_Width = _GDIPlus_ImageGetWidth($hOnlineChar)

    [/autoit][autoit][/autoit][autoit]

    $iMainChar_Height = _GDIPlus_ImageGetHeight($hMainChar)
    $iOnlineChar_Height = _GDIPlus_ImageGetHeight($hOnlineChar)

    [/autoit][autoit][/autoit][autoit]

    $hGrafik = _GDIPlus_GraphicsCreateFromHWND($Form1)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(331, 245, $hGrafik)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit]

    While 1
    Tick() ; Ruft alle Funktionen auf !
    WEnd

    [/autoit][autoit][/autoit][autoit]

    Func _MainDraw($Obj, $X, $Y, $Width, $Height, $Obj_1, $X_1, $Y_1, $Width_1, $Height_1)
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $hBackground, 0, 0, 373, 260)
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Obj, $X, $Y, $Width, $Height)
    _GDIPlus_GraphicsDrawImageRect($hBuffer, $Obj_1, $X_1, $Y_1, $Width_1, $Height_1)
    _GDIPlus_GraphicsDrawImage($hGrafik, $hBitmap, 0, 0)
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func Tick()
    Recv()
    _Steuerung()
    _MainDraw($hMainChar, $iMainChar_X, $iMainChar_Y, $iMainChar_Width, $iMainChar_Height, $hOnlineChar, $iOnlineChar_X, $iOnlineChar_Y, $iOnlineChar_Width, $iMainChar_Height)
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func Recv()
    Local $aRecvData2, $spData
    $aRecvData2 = UDPRecv($tBindSocket, 2048)
    If $aRecvData2 <> "" Then
    $spData = StringSplit($aRecvData2, ";")
    If $spData[0] == 2 Then
    $iOnlineChar_X = $spData[1]
    $iOnlineChar_Y = $spData[2]
    EndIf
    EndIf
    EndFunc

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func _Steuerung()
    Select
    Case _IsPressed(25)
    $iMainChar_X -= 2
    Case _IsPressed(26)
    $iMainChar_Y -= 2
    Case _IsPressed(27)
    $iMainChar_X += 2
    Case _IsPressed(28)
    $iMainChar_Y += 2
    EndSelect
    EndFunc

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func _Exit()
    _GDIPlus_GraphicsDispose($hGrafik)
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_ImageDispose($hMainChar)
    _GDIPlus_ImageDispose($hOnlineChar)
    _GDIPlus_ImageDispose($hBackground)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]

    Sender~

    [autoit]

    #RequireAdmin
    HotKeySet("{F1}", "_Senden")

    [/autoit][autoit][/autoit][autoit]

    Func _Senden()
    Local $iPostion_X = Random(20, 245, 1) , $iPostion_Y = Random(10, 331, 1)
    Local $sIP = "127.0.0.1", $iPort = 2266
    Local $tMainSocket
    Local $iSendBytes
    $tMainSocket = UDPOpen($sIP, $iPort)
    $iSendBytes = UDPSend($tMainSocket, $iPostion_X & ";" & $iPostion_Y)
    If $iSendBytes = 0 Then
    MsgBox(16, "Fehler", "Es gab ein Fehler beim Senden !")
    EndIf
    EndFunc

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    While 1
    Sleep(300)
    WEnd

    [/autoit]
  • Zitat


    Im Server reicht UDPBind, UDPOpen brauchst du nicht. Du hast in beiden Skripten UDPShutdown vergessen, in dem Client sogar UDPStartup.

    Ja habe ich heute morgen auch gesehen :P * war schon zu *


    So ich habe bis jetzt ja nur einen Playeranzeigen lassen jetzt würde ich das ganze gerne per Server machen also das der Client nicht mehr alles macht ?
    dies sollte doch auch möglich sein oder ?

  • So ich habe bis jetzt ja nur einen Playeranzeigen lassen jetzt würde ich das ganze gerne per Server machen also das der Client nicht mehr alles macht ?
    dies sollte doch auch möglich sein oder ?


    :?: Der Server macht doch schon fast alles, der Client sendet doch in deinem letzten Post nur seine Position.

  • Zitat

    Der Server macht doch schon fast alles, der Client sendet doch in deinem letzten Post nur seine Position.


    Bis jetzt habe ich die Charakter ja selber gezeichnet doch jetzt würde ich gerne das automatisch machen ...

    Zum Beispiel wenn ich mit Client_A auf den Server Connecte und jetzt mit Client_B zum Server Connecte das in Client_A im Client_B angezeigt wird und anders rum ?

  • Das könntest du entweder mit Adlib oder in einer Schleife mit Sleep() lösen, damit jeder Client alle x Millisekunden automatisch neuzeichnet, oder dass der Server immer wenn nötig sowas wie "REDRAW" oder was auch immer schickt und die Clients darauf reagieren.
    Das könnte dann so aussehen:

    [autoit]

    ;...
    $data = UDPRecv($tMainSocket)
    If @error Then
    ; Verbindung zum Server vermutlich unterbrochen
    ElseIf $data = "REDRAW" Then
    Tick()
    ElseIf $data <> "" Then
    ; Falls Daten gesendet wurden, die man andersweitig verwenden kann, zum Beispiel die Position eines anderen Spielers
    EndIf
    ;...

    [/autoit]

    Edit: Ich sehe gerade, dass du den UDPServer in den Client des Spiels eingebaut hast. 8| Ein selbstständiger Server, der nur die Clients verwaltet in Verbindung mit Clients, die nur ihre eigenen Daten verarbeiten und gegebenenfalls dem Server schicken wäre um einiges besser (zumindest aus meiner Sicht).

  • Danke James1337 :)

    Doch habe ich mich heute morgen Informiert das TCP, besser sei wegen der Prüfung der Pakten ?
    Ich habe mal angefangen meinen neuen Client zu Schreiben :) jetzt habe ich ein paar Vars gesetzt wollte mal fragen ob das so richtig ist

    [autoit][/autoit][autoit][/autoit][autoit]

    Global $sIP = "127.0.0.1", $iPort = 2266, $iMaxConnection = 50 ; Maximale Clients
    Global $aClient[$iMaxConnection + 1][3]
    $aClient[0][0] = $iMaxConnection
    Global $hCharaker[$iMaxConnection][$iMaxConnection][$iMaxConnection] ; IMAGE ; WIDTH, HEIGHT
    $hCharaker[0][0][0] = $iMaxConnection

    [/autoit]
  • Bei TCP kannst du dir sicher sein, dass alle Packete ankommen.
    Bei UDP ist das nicht, dafür ist es (angeblich) aber schneller, und die Fehlerquote ist anscheinend so gering, dass es trotzdem noch für Spiele genutzt wird, weil die Daten sowieso nach kurzer Zeit wieder gesendet werden, falls sie mal bei einem Client nicht ankommen.
    Außerdem musst du die Clients nicht akzeptieren und sendest/empfängst direkt auf dem Socket des Servers, was dir solche Arrays mit Clients vielleicht erspart. Wenn du das aber mit TCP schaffst, kannst du es natürlich auch so machen.

    [autoit]

    Global $hCharaker[$iMaxConnection][$iMaxConnection][$iMaxConnection] ; IMAGE ; WIDTH, HEIGHT

    [/autoit]

    kann man doch durch

    [autoit]

    Global $hCharaker[$iMaxConnection][3] ; IMAGE ; WIDTH, HEIGHT

    [/autoit]

    ersetzen, dann kann man auch für jeden Client IMAGE, WIDTH und HEIGHT speichern, oder liege ich da falsch?

    MfG, James

  • Also wenn ich das so

    [autoit]


    Global $hCharaker[$iMaxConnection][$iMaxConnection][$iMaxConnection] ; IMAGE ; WIDTH, HEIGHT

    [/autoit]

    machen würde den würde das nicht gehen oder was ?

  • Na die Player Information also diese für GDI

    [autoit]

    _GDIPlus_ImageLoadFromFile()
    _GDIPlus_ImageGetWidth()
    _GDIPlus_ImageGetHeight()

    [/autoit]
  • Ah Ok Danke :)

    Den sollte es ja keine Probleme mit diesen Code geben :?

    [autoit]

    Global $aPlayer[$iMaxConnection][5] ; | [0] IMAGE [1] Width [2] Height [3] X [4] Y

    [/autoit]

    ?(