Socket.h unter Windows

Tikonteroga

Erfahrenes Mitglied
Hallo,

Ich möchte mit Eclipse und MinGW unter Windows eine Anwendung entwickeln, die über TCP/IP kommuniziert.

Leider kann ich den Header <sys/socket.h> nicht einbinden? Kann ich diese für denMinGW irgendwo beziehen?

Gruß Tikonteroga
 
Hallo,

danke für die Antwort. Mit der winsock2.h habe ich jetzt gearbeitet.

Ich hätte da noch eine Frage.

Ich muss konkret über TCP ein höheres Protokol implementieren. Bei diesem höheren Protokol wird vom Client pro Nachricht immer ein Befehl (BYTE) und abhängig vom Befehl eine bestimmte Menge an Daten gesendet (REQUEST). Der Server muss dann abhängig vom Befehl immer innerhalb einer bestimmten Zeit antworten (RESPONSE), ansonsten muss eine bestimmte Fehlerbehandlung erfolgen (z. B. Wiederholung des Request).

Ich bräuchte hierfür eine recv Funktion, der ich vorgeben kann wieviele Bytes empfangen werden sollen und wie lange (in Millisekunden) die Funktion auf die Daten warten soll. Es gäbe dann den Fall das die Funktion durch den Timeout beendet wird oder durch den Empfang des vollständigen Datenpackets ...

Hättet ihr für mich einen Tipp ? Ich würde ungern in einer Schleife rumpollen oder ähnliches ...

Ich habe jetzt auch mal rumgesucht und bin auf die die setsockopt Funktion gestoßen.

Diese müsste ich vor jedem Request verwenden, um den Timeout für die recv Funktion festzulegen.

also:

setsockopt(...);
send(...);
recv(...);
 
Allerdings zu beachten:
MSDN hat gesagt.:
If a send or receive operation times out on a socket, the socket state is indeterminate, and should not be used; TCP sockets in this state have a potential for data loss, since the operation could be canceled at the same moment the operation was to be completed.
Nach dem Timeout kannst den Socket zumachen.
 
Hi.

Beachte aber, das der Socket nach einem Timeout nicht mehr verwendet werden kann. Du müßtest die Verbindung neu aufbauen.

Gruß
 
Hallo,

danke für den wichtigen Hinweis.

Ich bin jetzt kein Spezialist für Kommunikationsprotokol, aber glaube dass es kein guter Entwurf ist, wenn das Höhere Protokol die niedrigeren Protokolle abschießen kann...

Ich werde das mit dem Timeout wohl anderst lösen müssen.

Gibt es vielleicht eine möglichkeit, dass ich mich informieren lassen kann, wenn ein TCP Packet empfangen wurde. Dann könnte ich es so realisieren, dass ich nach einem Send einen Timer starte und dann warte ob mich zuerst der Timer oder die Winsock2 informiert ?
 
Hallo,

vielen Dank, das werde ich mir mal genauer anschauen.

Ich hab jetzt auch mal ein Bisschen gegrübelt, wie ich so vom Konzept her vorgehen soll.

Ich werde den Protokol und den Transport Layer voneinander trennen. Beim Transport Layer werde ich folgendermaßen vorgehen.

Ich werde wohl eine Funktion InitSlave() und DeinitSlave() erstellen. Diese Funktionen sind für das Herstellen bzw. Beenden einer TCP-Verbindung zuständig. Für jeden Slave erstelle ich einen HANDLE in dem Socket, IP-Addresse, Port, ... gespeichert sind.

Dann gibt es noch eine Command Funktion. Diese muss nach InitSlave() und vor DeinitSlave() verwendet werden. Mit dieser Funktion kann ich Daten versenden. Die Funktion wird entweder nach einem Timeout oder dem Empfang von Daten beendet.


Code:
//Verbindung mit dem Slave herstellen
extern void InitSlave(HANDLE* handle);

//Verbindung mit dem Slave schließen
extern void DeinitSlave(HANDLE* handle);

//Gibt die Anzahl der tatsächlich empfangenen Bytes zurück oder TIMEOUT
//request: Sendepuffer
//response: Empfangspuffer
//reqLength: Anzahl der zu sendenden Bytes
//respLength: Anzahl der zu empfangenen Bytes
//timeout: Timeout in ms
extern int32_t Command(HANDLE* handle, void* request, uint16_t reqLength, void* response, uint16_t respLength, uint16_t timeout);

Gibt es Anregungen, Kritik oder Verbesserungsvorschläge zu diesem Ansatz ?
 
Zuletzt bearbeitet:
Um zu verhindern, dass ein recv() blockt und nur mit einem Timeout unterbrochen werden kann, der den ganzen Socket unbrauchbar macht, darfst du recv() nur aufrufen, wenn es was zu lesen gibt.
So kannst du dein Timeout setzen, ohne den socket unbrauchbar zu machen.

Code:
bool readable(SOCKET socket)
{
    FD_SET fdSet;
    TIMEVAL timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    long status;

    FD_ZERO(&fdSet);
    FD_SET(socket,&fdSet);
    status = select(0,&fdSet,0,0,&timeout);
    if(status <= 0)
      {
          FD_ZERO(&fdSet);
      }
    if(!FD_ISSET(socket,&fdSet))
      {
          return false;
      }
    return true;
}




if(readable(MySocket))
  {
       rc = recv(MySocket,MyBuffer,MyMaxSize,0);
  }
else
  {
     // hier kannst du timeout checken
  }
 
Zurück