Zeitüberschreitung für Winsock recvfrom festlegen

Lesezeit: 4 Minuten

Benutzer-Avatar
Cory Carlson

Ich versuche, einen blockierenden Socket für das Timeout einzurichten, nachdem 16 ms versucht wurde, recvfrom() an einem Port auszuführen. Plattform ist Windows. Ich habe mir unzählige Beispiele online angesehen und es scheint wirklich einfach zu sein, ich kann es einfach nicht zum Laufen bringen. Jede Hilfe wäre willkommen!

#include <winsock2.h>
#include <string>

#pragma comment(lib, "ws2_32.lib")

#define PORT_NUM 8001

int main(void)
{
  std::string localIP;
  sockaddr_in localAddr;
  sockaddr_in remoteAddr;
  hostent* localhost;
  char buffer[1024];
  WSADATA wsData;

  int result = WSAStartup(MAKEWORD(2,2), &wsData);  // winsock version 2

  localhost = gethostbyname("");
  localIP   = inet_ntoa(*(in_addr*)*localhost->h_addr_list);

  localAddr.sin_family       = AF_INET;
  localAddr.sin_port         = htons(PORT_NUM);             // Set Port Number
  localAddr.sin_addr.s_addr  = inet_addr(localIP.c_str());  // Set IP Address

  int mHandle = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);

  if(mHandle == INVALID_SOCKET)
    return 1;


  if(bind(mHandle, (SOCKADDR*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR)
    return 1;

  timeval tv;
  tv.tv_sec  = 0;
  tv.tv_usec = 1600;

    // Set Timeout for recv call
  if(setsockopt(mHandle, SOL_SOCKET, SO_RCVTIMEO, 
                reinterpret_cast<char*>(&tv), sizeof(timeval)))
    return 1;

  int length = sizeof(remoteAddr);

  // <-- Blocks here forever
  recvfrom(mHandle, buffer, 1024, 0, (SOCKADDR*)&remoteAddr, &length);  

  return 0;
}

/*  I've also tried passing the time like so:
int ms = 16;

if(setsockopt(mHandle, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char*>(&ms), sizeof(int)))
  return 1; */

  • SO_RCVTIMEO ist nicht sehr portabel – welche Plattform verwenden Sie?

    – Messstab

    1. Dezember 2009 um 7:17 Uhr

  • Sie möchten wahrscheinlich die verwenden select Funktion

    – Laura

    1. Dezember 2009 um 9:37 Uhr

  • Hey danke! Ja, ich habe mir Select angeschaut und es zum Laufen gebracht!

    – Cory Carlson

    1. Dezember 2009 um 22:15 Uhr

  • Hinweis für zukünftige Leser: 1600 Mikrosekunden sind nicht gleich 16 ms.

    – Ben Voigt

    9. Februar 2018 um 23:05 Uhr

  • Die winsoc2-Dokumentation von Windows besagt, dass SO_RCVTIMEO ein DWORD in Millisekunden ist. Corys letzter Versuch war richtig. Ich bin mir nicht sicher, warum es nicht funktioniert, vielleicht der reinterpret_cast. Verwenden Sie stattdessen… (const char *)&ms.

    – Gabe Halsmer

    20. Februar 2018 um 0:48 Uhr


Ich habe mir die Auswahlfunktion angesehen und wie Laura gesagt hat, dass ich es tun sollte, und es ganz einfach zum Laufen gebracht! Vielen Dank!

fd_set fds ;
int n ;
struct timeval tv ;

// Set up the file descriptor set.
FD_ZERO(&fds) ;
FD_SET(mHandle, &fds) ;

// Set up the struct timeval for the timeout.
tv.tv_sec = 10 ;
tv.tv_usec = 0 ;

// Wait until timeout or data received.
n = select ( mHandle, &fds, NULL, NULL, &tv ) ;
if ( n == 0)
{ 
  printf("Timeout..\n");
  return 0 ;
}
else if( n == -1 )
{
  printf("Error..\n");
  return 1;   
}

int length = sizeof(remoteAddr);

recvfrom(mHandle, buffer, 1024, 0, (SOCKADDR*)&remoteAddr, &length); 

  • Soweit ich weiß, senden Sie ihm also jedes Mal, wenn Sie Ihre Anwendung ausführen, nur ein Paket. Angenommen, Sie senden Tausende von Paketen in einer Schleife, dieser Code kann abstürzen! Wie werden Sie dieses Problem lösen?

    – Ahx

    1. Januar 2016 um 21:26 Uhr

  • Dies ist die beste Antwort. Die andere Antwort – SO_RCVTIMEO als DWORD – wird die recvfrom timeout, aber es gibt ein paar Probleme: 1) Wenn Timeout auftritt, befindet sich der Socket nicht mehr in einem gültigen Zustand. 2) Ich konnte keine Windows-Dokumente finden, die erklärten, wie man das Timeout ausschaltet … aber da Ihr Socket ungültig wird, müssen Sie wahrscheinlich sowieso einen neuen erstellen.

    – Gabe Halsmer

    20. Februar 2018 um 15:31 Uhr

Benutzer-Avatar
joseAndresGomezTovar

Ich habe es versucht, indem ich es wie folgt weitergegeben habe

     int iTimeout = 1600;
     iRet = setsockopt( pSapManager->m_cSocket,
                        SOL_SOCKET,
                        SO_RCVTIMEO,
                        /*
                        reinterpret_cast<char*>(&tv),
                        sizeof(timeval) );
                        */
                        (const char *)&iTimeout,
                        sizeof(iTimeout) );

und führe es aus!!

  • Hallo, willkommen bei SO. Bitte versuchen Sie, Ihre Antwort in Worten zu erklären, nicht nur in Code. Es wird für alle einfacher sein, auf diese Weise zu lernen. Da Sie eine alte Frage beantworten, wie unterscheidet sich Ihre Antwort von den anderen Antworten?

    – Olle Sjögren

    7. November 2012 um 9:17 Uhr

  • Aus der Dokumentation: The level at which the option is defined (for example, SOL_SOCKET). SO_RCVTIMEO DWORD Sets the timeout, in milliseconds, for blocking receive calls.

    – Andreas

    14. April 2018 um 21:34 Uhr

WINDOWS: Timeout-Wert ist ein DWORD in Millisekunden, die an setsockopt() übergebene Adresse ist const char *

LINUX: Der Timeout-Wert ist ein struct timeval, die an setsockopt() übergebene Adresse ist const void *

Quelle: http://forums.codeguru.com/showthread.php?t=353217

Ich vermute Windows aus dem Aufruf von WSASocket(). Wenn ja, übergeben Sie das Timeout falsch.

MSDN sagt, dass SO_RCVTIMEO einen int-Parameter akzeptiert, der das Timeout in ms angibt.

1257510cookie-checkZeitüberschreitung für Winsock recvfrom festlegen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy