Re: Winsock CGI

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Andreas Born (Andreas.Born_at_gmx.de)
Date: 04/25/04


Date: Sun, 25 Apr 2004 20:49:13 +0200

Hallo Jan,

> ersteinmal danke für deinen Beitrag.
> Leider versteh ich das ganze nicht.

> Ich versuche hier verzweifelt einen Eintrag in meinem Gästebuch zu
> machen. Könntest du es mir vielleicht etwas einfacher erklären, wie
> das gemacht wird.

Ich habe doch beinahe schon den ganzen Code gepostet :)

1. Du brauchst folgende Informationen:

Host
Port
Path
QueryString

Diese musst Du irgendwie aus der URL ermitteln.

Allgemeine Form der Url:
   protokoll://username:passwort@host:port/path?QueryString
Oder ohne username und port:
   protokoll://host/path?QueryString

path schließt hierbei das eigentliche dokument/script mit ein, z.b.
path = pfad/zur/gewünschten/datei.html

Wenn kein port angegeben ist, wird der standardport (80) verwendet,
ansonsten der angegebene.

mit:

With Winsock1
    .Close
    .Protocol = sckTCPProtocol
    .RemoteHost = Host
    .RemotePort = Port
    .Connect
End With

weist du das Winsock-COntrol an, sich mit dem entsprechenden Host und
Port zu verbinden. Ist die Verbindung erfolgreich, wird das Ereignis
Winsock1_Connect ausgelöst. In diesem Ereignis wird die HTTP-Anfrage an
den Server gesendet:

Private Sub Winsock1_Connect()
  dim buf as string
    buf = '... HTTP-Anfrage erstellen
    Winsock1.SendData buf
End Sub

Vorher muß natürlich die HTTP-Anfrage mit den Formulardaten (dem Eintrag
für Gästebuch) erstellt werden. Dazu werden erstmal die Formulardaten
kodiert. Die folgende funktion ersetzt alle Sonderzeichen durch die
kodierung "%" + 2-stelliger HEXCode.

Private Function encode(s as string) as string
 dim i as long, ret As String, h as String
  for i = 1 to len(s)
    select case mid$(s,i,1)
      case 'a' to 'z', 'A' to 'Z', '0' to '9', '_':
        ret = ret & mid$(s,i,1)
      case else:
        h = hex$(asc(mid$(s,i,1)))
        do while len(h) < 2
          h = "0" & h
        loop
        ret = ret & "%" & h
    end select
  next i
  encode = ret
end Function

Hier wird der String gebildet, der als POST-Data an den server gesendet
wird, und zwar ind er Form:

Variable1=Wert1&Variable2=Wert2&.....

wobei die Variablenbezeichner und die Werte jeweils kodiert werden.

>> PostData = encode("name") & "=" & encode(name) & "&" & _
>> encode("herkunft") & "=" & encode(herkunft) & "&" & _
>> encode("kommentar") & "=" & encode(kommentar) & "&" & _
>> encode("eintragen") & "=" & encode(eintragen)

Da nun die zu sendenden Formulardaten fertig sind, ist auch deren Länge
bekannt, und es kann der HTTP-Header gebeildet werden:

   buf = _
     "POST " & Path & " HTTP/1.0" & vbcrlf & _
>> "HOST: " & Host & vbcrlf & _
>> "Accept: */*" & vbcrlf & _
>> "Referer: " & vbcrlf & _
     "Connection: Close" & vbcrlf & _
>> "Content-Length: " & cstr(len(PostData)) & vbcrlf & _
>> "Content-Type: application/x-www-form-urlencoded" & vbcrlf & _
>> vbcrlf & _
>> PostData

Hierzu wurden die Variablen Path, Host und PostData verwendet.
In der Ersten Zeile sollte HTTP/1.0 stehen, dann ist die Antwort besser
auszuwerten. Außerdem ist es ratsam, "Connection: Close" mitzusenden.

Weil nicht alles in eine Zeile passt, hab ich diese mit dem Unterstrich
'_' aufgeteilt. Dies dient also nur der Lesbarkeit und hat sonst keine
Funktion.

Jeder Headereintrag muß mit vbCRLF (den Zeilenendezeichen) abgeschlossen
werden, der gesamte Header wird von den POST-Daten ebenfalls nocheinmal
mit vbCRLF getrennt.

Diesen String sendest Du nun im Winsock_Connect-Ereignis.
Die Antwort kommt in kleinen Paketen an. Winsock löst dann das Ereignis
Winsock_DataArrival(...) aus.

"data" ist eine von Dir in der Form deklarierte Variable, an die Du alle
empfangenen Daten anhängst:

Private Sub Winsock_DataArrival(...)
 Dim r As String
   Winsock1.GetData r, vbString
   data = data & r
End Sub

Ist die Antwort komplett, beendet der Server die Verbindung, weil Du
dies mit "Connection:Close" angefordert hast. Dadurch wird das
Winsock_Close()-Erreignis ausgelöst, was dir mitteilt, daß die Antwort
komplett ist.

Private Sub Winsock1_Close()
  select case mid$(data,10,3)
    Case "200": Msgbox "Anfrage erfolgreich"
    Case Else: Msgbox "Anfrage fehlgeschlagen"
  end select
  'Header von der Antwort "entfernen"
  data = Mid$(data,Instr(data,vbcrlf & vbcrlf) + 4)
  'data enthält nun den html-Code der Serverantwort.
End Sub

Das wars. HTTP über Winsock ist eben nicht ganz so einfach. Noch
ausführlicher kann ich es leider nicht erklären ;)

Viele Grüße,
Andreas



Relevant Pages

  • Re: Timer tickt nicht richtig
    ... 'wenn Datensatz in DataGrid selektiert ist, TabelleDG2 gefiltert ... Sub LoadDataset(ByVal OleDBConn As OleDb.OleDbConnection, ... ByVal Criteria2 As String, _ ... End If ...
    (microsoft.public.de.german.entwickler.dotnet.vb)
  • Re: Strukturiertes Programm
    ... >> (Die Sub ist schon vorhanden) ... >Dein Hauptproblem ist der Datentyp String Deines an die Sub übergebenen ... > End Enum ... >Private Function Fkt1() As String ...
    (microsoft.public.de.vb)
  • Re: Strukturiertes Programm
    ... > (Die Sub ist schon vorhanden) ... Dein Hauptproblem ist der Datentyp String Deines an die Sub übergebenen ... End Enum ... Private Function Fkt1() As String ...
    (microsoft.public.de.vb)
  • Objektnamen in VBA anpassen
    ... Private Sub cmdGetFolder_Click ... On Error GoTo Err_cmdGetFolder_Click ... End Sub ... Dim DefaultPath As String, strFile As String ...
    (microsoft.public.de.access)
  • Project Error
    ... Private Declare Sub Sleep Lib "Kernel32" ... Dim strDataSrc As String ...
    (microsoft.public.vb.bugs)