Wie rohe ANSI Daten mit WinSock Lib senden? Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

Fluschi

Wie rohe ANSI Daten mit WinSock Lib senden?  Topic is solved

05 Oct 2018, 16:26

Guten Tag euch.


Ich sitze schon etwas länger an einem Problem womit ich nicht weiter komme, deshalb frage ich euch um Hilfe.

Ich erkläre eben kurz und knapp was ich vorhabe....

Ich lese ein kleines Bild mit FileOpen() und den passenden Parametern ein und ermittel danach die byte länge der rohen ANSI Daten.

Dann versende ich Sie mit ---> http://ahkscript.org/germans/forums/vie ... 789b388655

Auf der anderen Seite der Verbindung kommt aber nur die länge der Daten an, aber nicht die Binären Daten an sich selber. Was mache ich falsch?

Oder gibt es eine bessere Lib um das zu bewerkstelligen die mir Länge und die rohen ANSI Daten sendet und empfängt sodass ich sie mit FileOpen() zusammen setzen kann?

Falls Ihr eine Idee habt könntet Ihr es mir erklären und gegebenenfalls ein Beispiel stellen? Solltet Ihr noch mehr Infos brauchen sodass Ihr mir helfen könnt, gebt bescheid.

Gruß Fluschi.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

06 Oct 2018, 03:07

Moin,

zeig doch mal, wie Deine Skripte (Server / Client) bisher aussehen. Dann können wir zumindest mal schauen, ob Du etwas falsch machst.
Fluschi

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

06 Oct 2018, 07:04

Klar hier sind Server und Client.

Code: Select all

SetBatchLines -1
#NoEnv
#Include, WS.ahk
#Persistent
SetWorkingDir %A_ScriptDir%
OnExit, shutdown

WS_LOGTOCONSOLE=1
WS_Startup() ;Starte Winsock 2.0
client := WS_Socket("TCP", "IPv4") ;Erstelle neue TCP/IP Verbindung für IPv4
WS_Connect(client, "192.168.2.117", "12345") ;Verbinde zum Server (lokale IP 127.0.0.1) mit Port 12345
OnExit, shutdown


file := FileOpen(A_Desktop "\test.png", 1)

if !IsObject(file)
{
    MsgBox Can't write %file% !
    return
}

if IsObject(file)
{
	WS_RecvBinary(client, rawdata, len) ;Warte auf eingehende Nachricht
	Byteslength := WS_MessageSize(client)
	File.Write(rawdata)
	File.Close()
	return
}


shutdown:
WS_CloseSocket(client) ;Schließe die Verbindung
WS_Shutdown() ;Beende Winsock 2.0
ExitApp
return

Code: Select all

SetBatchLines -1
#NoEnv
#Include, WS.ahk
#Persistent
SetWorkingDir %A_ScriptDir%
OnExit, shutdown

WS_NOLOG := 0 ;Zeige den Log in keinem Konsolenfenster.
WS_LOGTOCONSOLE=1
WS_Startup() ;Starte Winsock 2.0
server := WS_Socket("TCP", "IPv4") ;Erstelle neue TCP/IP Verbindung für IPv4.
WS_Bind(server, "0.0.0.0", "12345") ;Binde die Verbindung an Port 12345.
WS_Listen(server) ;Erlaube den Client zu verbinden.
NewConnection := WS_Accept(server, client_ip, client_port) ;Warte auf Verbindung.


file := FileOpen(A_Desktop "\test.png", 0)

if !IsObject(file)
{
    MsgBox Can't open %file% !
    return
}

if IsObject(file)
{
	rawdata := File.Read()
	len := StrLen(rawdata)
	File.Close()
	WS_SendBinary(NewConnection, &rawdata, len) ;Sende Bild Daten.
	return
}

shutdown:
WS_CloseSocket(NewConnection) ;Schließe die Verbindung.
WS_CloseSocket(server) ;Schließe die Verbindung.
WS_Shutdown() ;Beende Winsock 2.0
ExitApp
return
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

06 Oct 2018, 22:28

OK.

Eine PNG-Datei enthält keine 'rohen ANSI-Daten' sondern binäre Daten inklusive Null-Bytes. Damit AHK solche Inhalte unverändert lesen und schreiben kann, verfügt das File-Objekt über die Methoden RawRead() und RawWrite(). Die Anzahl der Bytes liefert beim Lesen die Eigenschaft Length.

Wenn Du die Daten mit den für Textdateien gedachten Methoden File.Read(), File.Write() bzw. StrLen()verarbeitest, behandelt AHK sie als ANSI- bzw. Unicode-Zeichenketten. Null-Bytes bedeuten dann das Ende der Zeichenkette und die Daten werden mit sehr großer Wahrscheinlichkeit verstümmelt.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

07 Oct 2018, 01:00

Zudem öffnest du die selbe Datei 2 mal gleichzeitig. Das geht nicht.
Recommends AHK Studio
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

07 Oct 2018, 04:21

Nachschlag:

Ich habe unterstellt, dass die Skripte auf zwei unterschiedlichen Rechnern laufen. Dann stellt sich das Problem des gleichzeitigen Zugriffs auf ein und dieselbe Datei nicht.

Anderenfalls gibt es ein Problem, wie nnnik schon sagte. Besonders das FileOpen(A_Desktop "\test.png", 1) im Serverskript ist dann gefährlich, weil es die Datei leert und dann darauf wartet, dass neue Daten kommen.
Fluschi

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

07 Oct 2018, 09:05

Guten Tag euch,

Danke für eure Hilfe und die Erklärungen usw. ich habe das jetzt abgeändert von File.Read | File.Write zu ----> File.RawRead | File.RawWrite

aber leider kommen immer noch nicht die Binären Daten an ich sende nochmal die überarbeiteten Skripte.

Code: Select all

SetBatchLines -1
#NoEnv
#Include, WS.ahk
#Persistent
SetWorkingDir %A_ScriptDir%
OnExit, shutdown

WS_LOGTOCONSOLE=1
WS_Startup() ;Starte Winsock 2.0
client := WS_Socket("TCP", "IPv4") ;Erstelle neue TCP/IP Verbindung für IPv4
WS_Connect(client, "192.168.2.117", "12345") ;Verbinde zum Server (lokale IP 127.0.0.1) mit Port 12345
OnExit, shutdown


File := FileOpen(A_Desktop "\test2.png", 1)

if !IsObject(file)
{
    MsgBox Can't write %file% !
    return
}

if IsObject(file)
{
	WS_RecvBinary(client, rawdata, len) ;Warte auf eingehende Nachricht
	File.RawWrite(rawdata, len)
	File.Close()
	return
}


shutdown:
WS_CloseSocket(client) ;Schließe die Verbindung
WS_Shutdown() ;Beende Winsock 2.0
ExitApp
return

Code: Select all

SetBatchLines -1
#NoEnv
#Include, WS.ahk
#Persistent
SetWorkingDir %A_ScriptDir%
OnExit, shutdown

WS_NOLOG := 0 ;Zeige den Log in keinem Konsolenfenster.
WS_LOGTOCONSOLE=1
WS_Startup() ;Starte Winsock 2.0
server := WS_Socket("TCP", "IPv4") ;Erstelle neue TCP/IP Verbindung für IPv4.
WS_Bind(server, "0.0.0.0", "12345") ;Binde die Verbindung an Port 12345.
WS_Listen(server) ;Erlaube den Client zu verbinden.
NewConnection := WS_Accept(server, client_ip, client_port) ;Warte auf Verbindung.


File := FileOpen(A_Desktop "\test.png", 0)

if !IsObject(file)
{
    MsgBox Can't open %file% !
    return
}

if IsObject(file)
{
	len := File.Length
	bytes := File.RawRead(rawdata, len)
	File.Close()
	WS_SendBinary(NewConnection, &rawdata, bytes) ;Sende Bild Daten.
	return
}

shutdown:
WS_CloseSocket(NewConnection) ;Schließe die Verbindung.
WS_CloseSocket(server) ;Schließe die Verbindung.
WS_Shutdown() ;Beende Winsock 2.0
ExitApp
return
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

08 Oct 2018, 05:19

Moin,

ich habe mir WS.ahk aus dem ersten Beitrag in Deinem o.a. Link neu kopiert. (!!Z.Zt. ist der Link nicht erreichbar!!)

Die Funktion WS_RecvBinary() sieht bei mir so aus:

Code: Select all

WS_RecvBinary(socket, byref pbuffer, len, flags=0)
{
  static MSG_PEEK := 2, MSG_OOB := 1, MSG_WAITALL := 8

  Ptr := (A_PtrSize) ? "uptr" : "uint"
  fl := 0
  Loop, parse, flags, % " "
  {
    if (A_LoopField="MSG_PEEK")
      fl |= MSG_PEEK
    else if (A_LoopField="MSG_OOB")
      fl |= MSG_OOB
    else if (A_LoopField="MSG_WAITALL")
      fl |= MSG_WAITALL
  }
  WS_Log(A_ThisFunc "(" socket ", message, " len ", " flags ")", 3)
  result := DllCall("ws2_32\recv", Ptr, socket, Ptr, pbuffer, "int", len, "int", fl)
  if (result=-1)
  {
    WS_Log("[ERROR] Receiving failed!", 1)
    return 0
  }
  message := ""
  Loop, % result
    message .= Chr(NumGet(buffer, A_Index-1, "uchar"))
  message .= Chr(0)
  WS_Log(result " bytes received (binary)", 4)
  return result
}
Wenn das bei Dir auch so aussieht, hat Dein Clientskript echte Probleme. Außerdem überzeugt mich der Code grundsätzlich nicht. Ich würde folgende Änderungen vorschlagen:

WS.ahk:

Code: Select all

WS_RecvBinary(socket, byref buffer, len, flags=0) ; pbuffer -> buffer
{
  Static MSG_PEEK := 2, MSG_OOB := 1, MSG_WAITALL := 8

  Ptr := (A_PtrSize) ? "uptr" : "uint"
  fl := 0
  Loop, parse, flags, % " "
  {
    if (A_LoopField="MSG_PEEK")
      fl |= MSG_PEEK
    else if (A_LoopField="MSG_OOB")
      fl |= MSG_OOB
    else if (A_LoopField="MSG_WAITALL")
      fl |= MSG_WAITALL
  }
  WS_Log(A_ThisFunc "(" socket ", message, " len ", " flags ")", 3)
  VarSetCapacity(buffer, len, 0) ; neu
  result := DllCall("ws2_32\recv", Ptr, socket, Ptr, &buffer, "int", len, "int", fl) ; pbuffer -> &buffer
  if (result=-1)
  {
    WS_Log("[ERROR] Receiving failed!", 1)
    return 0
  }
;   message := ""
;   Loop, % result
;     message .= Chr(NumGet(buffer, A_Index-1, "uchar"))
;   message .= Chr(0)
  WS_Log(result " bytes received (binary)", 4)
  return result
}
Edit: Funktionsname korrigiert.

Ich habe das aber nicht getestet.
Last edited by just me on 08 Oct 2018, 10:40, edited 1 time in total.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Wie rohe ANSI Daten mit WinSock Lib senden?

08 Oct 2018, 09:41

Ich würde dir empfehlen nicht zu versuchen das Antike Ausgrabungsstück was du entdeckt hast zu reparieren sondern lieber die aktuelle Version zu verwenden.
GeekDude hat die Socket.ahk übernommen nachdem Bentschi sie nicht mehr aktualisiert hat.

Die aktuellste Version kannst du hier finden:
https://github.com/G33kDude/Socket.ahk
Recommends AHK Studio

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 25 guests