noch ein daten senden problem

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: noch ein daten senden problem

Beitrag von STARGÅTE »

Man schickt aber eigentlich keine einzelnen Longs durch Internet, da ist ja der Header und alle Protokolldaten größer ^^
Entweder du schickst die Zahlen als String mit rüber (gibt ja genügend Trennzeichen, w.z.B. TAB) oder du baust dir ausgehend von den Vorlagen hier im Forum deine eigene Prozedur.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Moxl
Beiträge: 150
Registriert: 26.10.2012 13:19

Re: noch ein daten senden problem

Beitrag von Moxl »

okaaay :o
das schmeißt jetzt meine ganze plaunung und alles um^^
du hast mir den den vorschlag in nem anderen beitrag gemacht x)

Code: Alles auswählen

ReceiveNetworkData(Client, @Type, 4)
Select Type
   Case #Datei
      ReceiveNetworkData(Client, @LaengeDateiName, 4)
   Case #Text
      ReceiveNetworkData(Client, @LaengeText, 4)
EndSelect
type ist ja ein long^^ und auf dem prinzip hab ich mir jetzt mein ganzes programm aufgebaut^^
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: noch ein daten senden problem

Beitrag von STARGÅTE »

Du hast aber den Hinweis "PseudoCode" zu diesem Code vergessen.
Natürlich kannst du diesen Code nicht in dieser Form verwenden (aus den bereits genannten Grunden bezüglich ReceiveNetworkData).

Natürlich sollst du nicht alles mittels Strings senden, das geht ja auch nicht immer.
Sondern, du sollst Code (von anderen oder mir) als Idee nehmen, bzw. als Vorlage.
Du kannst ja auch sowas senden:
"DateiName"+#Tab$+"Beispiel.txt"
"Text"+#Tab$+"Hallo Welt!"
Und die empfangenen Strings kannst du mit StringField() teilen und immer den Typ und Inhalt auslesen.
Auch nur eine Idee!

Du hast jetzt eine Planung gemacht, deswegen musst du auch selber ein dafür zugeschnittenes Include bauen.
Ich habe ein solches Include für mich geschrieben, was auch meine Bedürfnisse zugeschnitten ist.
Du hast jetzt für Strings eine möglichkeit bekommen und ich denke du kannst diese Möglichkeit schnell für andere Sachen umschreiben.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
schleicher
Beiträge: 214
Registriert: 30.03.2014 19:57
Computerausstattung: Purebasic 5.70
Wohnort: 18314 Löbnitz

Re: noch ein daten senden problem

Beitrag von schleicher »

STARGÅTE hat geschrieben:

Code: Alles auswählen

EnableExplicit

Structure ReceiveNetworkBlock
	Length.l
	Shift.i
	*Memory
	CurrentLength.i
EndStructure

Procedure.i SendString(ConnectionID.i, String.s)
	
	Protected Length.i = StringByteLength(String, #PB_UTF8)
	Protected CurrentLength.i, Result.i
	Protected *Buffer = AllocateMemory(SizeOf(Long)+Length+1)
	
	PokeL(*Buffer, Length)
	PokeS(*Buffer+SizeOf(Long), String, Length, #PB_UTF8)
	Repeat
		Result = SendNetworkData(ConnectionID, *Buffer, SizeOf(Long)+Length-CurrentLength)
		If Result > 0
			CurrentLength + Result
		ElseIf Result = -1
			FreeMemory(*Buffer)
			ProcedureReturn #False
		EndIf
	Until CurrentLength = SizeOf(Long)+Length
	FreeMemory(*Buffer)
	
	ProcedureReturn Length
	
EndProcedure

Procedure.s ReceiveString(ConnectionID.i)
	
	Static NewMap Connection.ReceiveNetworkBlock()
	Protected *Connection.ReceiveNetworkBlock, String.s
	Protected Key.s = Str(ConnectionID)
	Protected ReceiveLength.i, Length.i
	
	; Verbindungs suchen
	If FindMapElement(Connection(), Key)
		*Connection = Connection()
	Else
		*Connection = AddMapElement(Connection(), Key)
	EndIf
	If *Connection\Memory = #Null
		; Länge eines neuen Strings empfangen
		ReceiveLength = ReceiveNetworkData(ConnectionID, @*Connection\Length+*Connection\Shift, SizeOf(Long)-*Connection\Shift)
		If ReceiveLength > 0
			If ReceiveLength+*Connection\Shift = SizeOf(Long)
				*Connection\Memory = AllocateMemory(*Connection\Length+1)
			Else
				*Connection\Shift + ReceiveLength
			EndIf
		EndIf
	Else 
		; alten Strings weiter empfangen
		Length = *Connection\Length - *Connection\CurrentLength
		ReceiveLength = ReceiveNetworkData(ConnectionID, *Connection\Memory+*Connection\CurrentLength, Length)
		If ReceiveLength = Length
			String = PeekS(*Connection\Memory, *Connection\Length, #PB_UTF8)
			FreeMemory(*Connection\Memory)
			DeleteMapElement(Connection(), Key)
		ElseIf ReceiveLength > 0
			*Connection\CurrentLength + ReceiveLength
		EndIf 
	EndIf
	
	ProcedureReturn String
	
EndProcedure


InitNetwork()

CreateNetworkServer(1, 7000)
Define CID = OpenNetworkConnection("84.189.151.203", 7000)
Define String.s

Debug SendString(CID, "Hallo Welt!")
Debug SendString(CID, "Das ist eine andere Zeichenkette.")
Debug SendString(CID, "Hier kommt noch was langes: "+Space(4000)+" das wars.")
Debug SendString(CID, "Ende!")

Repeat
   If NetworkServerEvent() = #PB_NetworkEvent_Data
      String = ReceiveString(EventClient())
      If String : Debug Str(Len(String))+" : "+String : EndIf
   Else
      Delay(1)
   EndIf
ForEver

Nach soetwas habe ich gesucht für mein Telnet-Prog. Leider funktioniert der Code unter PB 5.51 nicht und ich weiß nicht warum. ReceiveString(ConnectionID.i) gibt keine Antwort vom Server zuück. Kannst du da nochmal helfen ?
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: noch ein daten senden problem

Beitrag von STARGÅTE »

Hallo Schleicher,

du musst natürlich die IP ändern. Ich hatte damals vermutlich eine Route mit hohem Ping gewählt, um dort die Funktionsfähigkeit zu testen. Es geht aber auch genauso mit 127.0.0.1
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
schleicher
Beiträge: 214
Registriert: 30.03.2014 19:57
Computerausstattung: Purebasic 5.70
Wohnort: 18314 Löbnitz

Re: noch ein daten senden problem

Beitrag von schleicher »

Hallo

IP und Port hatte ich geändert. Ich möchte dein Beispiel für eine Telnetverbindung (Linux Server)nutzen und sitze schon den ganzen Tag an dem folgendem Problem.
Receivestring() gibt den Fehler zurück, das beim Speicher bereitstellen der Wert negativ ist .

Der Befehl

Code: Alles auswählen

 ReceiveLength = ReceiveNetworkData(ConnectionID, @*Connection\Length+*Connection\Shift, SizeOf(Long)-*Connection\Shift)
erzeugt in der Map bei *Connection\Length den Minuswert aber ReceiveLength=4

Habe es auch schon mit meinem FTP Server(auch Linux Server) versucht. Dort ist der Wert nicht im Minusbereich, sondern in einem sehr hohen Plusbereich was auch nicht richtig ist.
Hier mein Testcode

Code: Alles auswählen

EnableExplicit

Structure ReceiveNetworkBlock
  Length.l
  Shift.i
  *Memory
  CurrentLength.i
EndStructure


Global ip.s="192.168.40.29"                  ; hier IP, port, user und pass anpassen
Global port=23
Global user.s="root"
Global pass.s="pass"
Global CID

Declare   Telnet_Connect(ip.s, port, user.s, pass.s)
Declare.i SendString(ConnectionID.i, String.s) 
Declare.s Receivestring(ConnectionID)



Procedure Telnet_Connect(ip.s, port, user.s, pass.s)
  Protected antwort.s, connect, ConnectionID_Telnet, *Connection, t
  Protected Key
  t=ElapsedMilliseconds()
  connect=0
  
  ConnectionID_Telnet=OpenNetworkConnection(ip, port)
 
  If ConnectionID_Telnet
    Delay(100)
    antwort= Receivestring(ConnectionID_Telnet)
    Debug "0  "+antwort
    
    If FindString(antwort, "login:", 1)
      SendString(ConnectionID_Telnet, user )
      antwort = Receivestring(ConnectionID_Telnet)
      Debug "1  "+antwort
    
      If FindString(antwort, "Last login")  ;Login erfolgt wenn der Server ohne Passwort läuft
        connect=1
      
      
      ElseIf FindString(antwort, "Password", 1)
        If SendString(ConnectionID_Telnet, pass )
          antwort= Receivestring(ConnectionID_Telnet)
          Debug "2  "+antwort
          If FindString(antwort, "Last login") ;Login mit Passwort erfolgt
            connect=1
          EndIf
        EndIf
      EndIf
    EndIf
    
    If connect=1
      ProcedureReturn ConnectionID_Telnet
    Else
      MessageRequester("Error", " Connection error ! Please check User, Pass and Telnet-Port  !", #MB_ICONERROR)
    EndIf
  EndIf 
EndProcedure

Procedure.i SendString(ConnectionID.i, String.s)
  
  Protected Length.i = StringByteLength(String, #PB_UTF8)
  Protected CurrentLength.i, Result.i
  Protected *Buffer = AllocateMemory(SizeOf(Long)+Length+1)
  
  PokeL(*Buffer, Length)
  PokeS(*Buffer+SizeOf(Long), String, Length, #PB_UTF8)
  Repeat
    Result = SendNetworkData(ConnectionID, *Buffer, SizeOf(Long)+Length-CurrentLength)
    If Result > 0
      CurrentLength + Result
    ElseIf Result = -1
      FreeMemory(*Buffer)
      ProcedureReturn #False
    EndIf
  Until CurrentLength = SizeOf(Long)+Length
  FreeMemory(*Buffer)
  
  ProcedureReturn Length
  
EndProcedure

Procedure.s Receivestring(ConnectionID)
  Static NewMap Connection.ReceiveNetworkBlock()
  Protected *Connection.ReceiveNetworkBlock, String.s
  Protected Key.s = Str(ConnectionID)
  Protected ReceiveLength.i, Length.i
  
  Debug "Verbindungs suchen"
  If FindMapElement(Connection(), Key)
    *Connection = Connection()
  Else
    *Connection = AddMapElement(Connection(), Key)
  EndIf
  If *Connection\Memory = #Null
    Debug"Länge eines neuen Strings empfangen"
    ReceiveLength = ReceiveNetworkData(ConnectionID, @*Connection\Length+*Connection\Shift, SizeOf(Long)-*Connection\Shift)
    If ReceiveLength > 0
      If ReceiveLength+*Connection\Shift = SizeOf(Long)
        *Connection\Memory = AllocateMemory(*Connection\Length+1)              ; *Connection\Length+1   ist hier negativ und bricht ab !
      Else
        *Connection\Shift + ReceiveLength
      EndIf
    EndIf
  Else
    Debug "alten Strings weiter empfangen"
    Length = *Connection\Length - *Connection\CurrentLength
    Debug "Lenght is "+Str(Length)
    ReceiveLength = ReceiveNetworkData(ConnectionID, *Connection\Memory+*Connection\CurrentLength, Length)
    Debug "Receivelenght = "+Str(ReceiveLength)+ "Length = "+Str(Length)
    If ReceiveLength = Length
      String = PeekS(*Connection\Memory, *Connection\Length, #PB_UTF8)
      FreeMemory(*Connection\Memory)
      DeleteMapElement(Connection(), Key)
    ElseIf ReceiveLength > 0
      *Connection\CurrentLength + ReceiveLength
    EndIf
  EndIf
  
  ProcedureReturn String
EndProcedure


InitNetwork()

CID=Telnet_Connect(ip.s, port, user.s, pass.s)

If CID
 Debug "Connection with User, Pass, telnet_port ok"
Else
  Debug "No Connection"
EndIf
Purebasic 5.51
schleicher
Beiträge: 214
Registriert: 30.03.2014 19:57
Computerausstattung: Purebasic 5.70
Wohnort: 18314 Löbnitz

Re: noch ein daten senden problem

Beitrag von schleicher »

Hat es vieleicht was mit der Textcodierung von Linux zu tun. Zeilenende, Zeilenumbruch ?
Purebasic 5.51
schleicher
Beiträge: 214
Registriert: 30.03.2014 19:57
Computerausstattung: Purebasic 5.70
Wohnort: 18314 Löbnitz

Re: noch ein daten senden problem

Beitrag von schleicher »

Keiner eine Idee ? Kann man die Länge des vom Server gesendeten String noch anders herausbekommen ?
Purebasic 5.51
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: noch ein daten senden problem

Beitrag von STARGÅTE »

Mir ist nicht ganz klar, um was es geht.

"Mein" ReceiveString() darf nur im Zusammenhang mit "meinem" SendString() verwendet werden.
Das heißt du kannst weder einen "fremden" String mit ReceiveString() empfangen, noch einem fremden Programm einen String mit SendString() senden.

Eine Telnetverbindung (Linux Server) nutzt vermutlich das Telnet-Protokoll (genauso wie es das HTTP- oder FTP-Protokoll gibt), du müsstest dich also mal mit dem Aufbau dieses Protokolls auseinander setzten, damit du nach diesen Regeln Daten senden und empfangen kannst (ähnlich wie du es ja bei HTTP oder FTP auch machen muss).

Bei HTTP bekommt man zB die Länge des Inhalts als Klartext mitgesendet.
Verarbeiten musst du die Daten dann wieder mit den "Grundbefehlen" ReceiveNetworkData und SendNetworkData

PS: Und ja, es ist u.a. sehr wichtig zu wissen in welchem Format Strings zurückgesendet werden und in welchem Format der Zeilenumbruch vorliegt. Steht vermutlich auch in der Dokumentation vom Telnet-Protokoll
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
schleicher
Beiträge: 214
Registriert: 30.03.2014 19:57
Computerausstattung: Purebasic 5.70
Wohnort: 18314 Löbnitz

Re: noch ein daten senden problem

Beitrag von schleicher »

STARGÅTE hat geschrieben: "Mein" ReceiveString() darf nur im Zusammenhang mit "meinem" SendString() verwendet werden.

Ich will as auch komplett so nutzen , aber wenn ich die OpenNetworkConnection(IP, port) anfordere, sendet der Server (Telnet) die Loginabfragen User und Passwort (bevor ich überhaupt SendString() benutzt habe).

Ich hatte die Telentverbindung schon selbst fertig geschrieben, doch ich hatte da ein Timing-Problem, wenn der Server länger braucht oder größere Informationen sendet dann gibt es Probleme mit dem empfangen. (Siehe Code unten) Info über das Telnetprotokoll sieht man hier :
http://wiki.blue-panel.com/index.php/BusyBox
Da finde ich aber keine Informationen, wie (mit welchen Zeilenumbruch usw.) der Server dann sendet
Hier ist ein Beispiel, wie die Verbindung mit User und Passwort funktioniert, was aber das genannte Problem hat.
Wie kann man das noch machen, das man auch alle Informationen sicher empfängt ?

Code: Alles auswählen

EnableExplicit
Global ConnectionID

Global IP.s="192.168.40.29"               ;hier anpassen
Global User.s="root"
Global Pass.s=""
Global Port=23

Declare    connect()
Declare    SendString(ConnectionID, String.s)
Declare .s GetString(ConnectionID, TimeOut = 5000)

InitNetwork()
ConnectionID=connect()
Debug ConnectionID

Procedure connect()
  Protected connec.s
  
  ConnectionID= OpenNetworkConnection(IP, Port)
  
  If ConnectionID
    
    connec.s = GetString(ConnectionID)
    Debug connec
    If FindString(connec, "login:", 1, #PB_String_CaseSensitive)
      SendNetworkString(ConnectionID, User +#CRLF$, #PB_Ascii)
      Delay(100)
      connec.s = GetString(ConnectionID)
      Debug connec
      Delay(100)
      If FindString(connec, "Password", 1, #PB_String_CaseSensitive)
        If SendNetworkString(ConnectionID, Pass +#CRLF$, #PB_Ascii)
          Delay(500)
          connec.s = GetString(ConnectionID)
          Debug connec
        EndIf
      EndIf
    EndIf
    ProcedureReturn ConnectionID
  Else
    MessageRequester("Error", "Please check IP and Port ! ", #MB_ICONERROR)
  EndIf
  
EndProcedure

Procedure SendString(ConnectionID, String.s)
  
  Protected Size, *Buffersend, Result = #Null
  
  String = String + #CRLF$
  Size = StringByteLength(String, #PB_UTF8) + 1
  
  *Buffersend = AllocateMemory(size)
  
  If *Buffersend
    PokeS(*Buffersend, String, Size, #PB_UTF8)
    Result = SendNetworkData(ConnectionID, *Buffersend, MemorySize(*Buffersend)-1)
    FreeMemory(*Buffersend)
  EndIf
  
  ProcedureReturn Result     
  
EndProcedure

Procedure.s GetString(ConnectionID, TimeOut = 5000)
  
  Protected *Buffer, t, Size, Text.s
  
  Delay(200)
  *Buffer = AllocateMemory(65536)
  t = ElapsedMilliseconds()
  
  If *Buffer
    
    While NetworkClientEvent(ConnectionID) <> 2 And ElapsedMilliseconds()-t < Timeout
      Delay(100)
    Wend
    
    Repeat
      Size=ReceiveNetworkData(ConnectionID, *Buffer,  65536)
      Text.s = PeekS(*Buffer, Size, #PB_UTF8)
      If Size<65536 
        Break
      EndIf
    ForEver
    
    FreeMemory(*Buffer)
    
    ProcedureReturn Text   
    
  EndIf
  
EndProcedure


Purebasic 5.51
Antworten