Home » Tutorials » Netzwerk und Internet » Sockets mit WinAPI

Sockets mit WinAPI

Fehlerbearbeitung

Bevor wir weiter in die Socketprogrammierung einsteigen, kümmern wir uns erstmal um Fehler. In dem Fall nicht um unsere, sondern primär um Fehler im Netzwerk oder Fehler über Windows. Das Fehlerhandling ist bei allen Socketoperationen nahezu identisch, deswegen können wir es in einem Kapitel abhaken.
Am besten ist es, wir machen das an einem Befehl, den wir bereits kennen: WSAStartUp. Hier können zwar noch keine Netzwerkfehler eintreffen, aber vielleicht ist ja Windows mit unserer Versionswahl unzufrieden. Jeder Socket-Befehl liefert einen 32-Bit-Wert (Integer) zurück. Wenn Dieser Wert die Konstante SOCKET_ERROR (oder bei einem Befehl auch INVALID_SOCKET) annimmt, lag ein Fehler vor. Diesen können wir mit WSAGetLastError abfragen. Aus WSAGetLastError bekommen wir den Fehlercode. Für eine Ausgabe als String benutzen wir (wie bei jedem anderen Fehler) FormatMessage aus der Kernel32.DLL (Unit Windows nicht vergessen) oder eben SysErrorMessage aus der Unit SysUtils (welche nur das FormatMessage kapselt).
Unsere InitSocket-Procedure von vorhin sieht mit Fehlerbehandlung evtl. so aus:

procedure InitSockets;
var   Data: WSAData;
      Res: Integer;
      ErrorCode: Integer;
      S: string;
      Len: Integer;
begin
  res := WSAStartup( MakeWord(1,1), Data);
  if Res = SOCKET_ERROR then
  begin
    // get error code
    ErrorCode := WSAGetLastError;

    //transform ErrorCode to string
    Setlength(s, 260);
    Len := Formatmessage(Format_Message_from_System,
      nil, errorCode, 0, @s[1], length(s), nil);
    Setlength(s, Len);

    //display error-string
    MessageBox(0, PChar(s), ’Socket Error’,
      MB_OK or MB_ICONERROR or MB_TASKMODAL);
  end;
end;
procedure HandleError;
var   ErrorCode: Integer;
      S: String;
      Len: Integer;
begin
  ErrorCode := WSAGetLastError;
  SetLength(s, 260);
  Len := Formatmessage(Format_Message_from_System,
    nil, errorCode, 0, @s[1], length(s), nil);
  Setlength(s, Len);
  MessageBox(0, PChar(s), ’Socket Error’,
    MB_OK or MB_ICONERROR or MB_TASKMODAL);
  //hier evtl noch ein RaiseException; je nach gewünschtem Konzept
end;

Da alle Socketfehler gleich behandelt werden, macht sich eine solche Vorgehensweise (Auswertung = Anzeige in MessageBox) natürlich am besten in einer separaten Procedure. Wir ändern das Programm deswegen etwas ab und setzen mal alles bisher zusammen:

procedure InitSockets;
var Data: WSAData;
begin
  if WSAStartup( MakeWord(1,1), Data) = SOCKET_ERROR then
    HandleERROR;
end;

initialization
  Initsockets;

finalization
  WSACleanup;

Ich werde im Folgenden die Fehlerbehandlung nicht mehr ausführlich aufschreiben. Ich werde nur noch auf Besonderheiten diesbezüglich hinweisen.
Es ist natürlich auch genauso gut möglich statt einer String-Auswertung inkl. Anzeige, dass der ErrorCode direkt ausgewertet wird. Die entsprechenden Konstanten sind in der Unit WinSock definiert und im Windows SDK beschrieben.

5 Gedanken zu „Sockets mit WinAPI“

  1. Wo findet sich denn der Link, um die Programmbeispiele herunterzuladen?
    Ich suche jetzt schon eine Weile, finde aber nichts.

  2. Eine weitere – aus meiner Sicht sehr wichtige – Antwort auf die Frage, warum man die Sockets selbst über die Windows API programmieren sollte, wäre noch:

    Ich hatte vor ca. 10 Jahren einen „Chat“ über die Komponenten von Delphi programmiert. Wir haben hier in der Firma einen Linux-Server zu stehen. Da die Leute das lustig fanden, ist der Chat heute fester Bestandteil. Linux bedeutet aber insoweit Probleme, weil ich das Programm emulieren lassen muss. Dafür würde sich theoretisch wine anbieten.
    Der Haken ist aber, dass die Komponenten alle fest in der VCL verankert sind und man mit wine nicht weit kommt. Man braucht also eine virtuelle Maschine mit Windows, um den Server laufen zu lassen. Insoweit erhoffe ich mir, dieses Problem eventuell lösen zu können. Wenn es mir gelingt, mit dieser Anleitung eine eigene Klasse ganz ohne jede VCL erstellen zu können, dann kann ich den Server als Konsolen-Programm erstellen und (endlich) ohne den ganzen Overhead unter wine laufen lassen.

    Falls den Seitenadmin dieser Kommentar stört, kann er ihn gern wieder gelöscht werden. Aber auf der Suche nach Sockets ohne VCL, wäre dies als Fund bei Suchmaschinen schon vor langer Zeit sehr hilfreich für mich gewesen. Suchmaschinen finden aber immer nur den Text, der auf den Seiten tatsächlich irgendwo steht und wenn man nach „nonvcl“ im Zusammenhang mit Sockets unter Delphi sucht, sieht es dünn aus mit den Suchergebnissen.

  3. Hallo, ich kann leider auch deine Programmbeispiele als Datei nicht finden. Sind die nicht mehr verlinkt?

    Ansonsten gutes Tutorial 🙂

Kommentare sind geschlossen.