ZFX
ZFX Neu
Home
Community
Neueste Posts
Chat
FAQ
IOTW
Tutorials
Bücher
zfxCON
ZFXCE
Mathlib
ASSIMP
NES
Wir über uns
Impressum
Regeln
Suchen
Mitgliederliste
Membername:
Passwort:
Besucher:
4396334
Jetzt (Chat):
23 (0)
Mitglieder:
5239
Themen:
24223
Nachrichten:
234554
Neuestes Mitglied:
-insane-

ZFX
Coding-Foren
Sourcecode-Probleme
Re: Socket verschluckt Daten :(
Normal
AutorThema
g_r00t Offline
ZFX'ler


Registriert seit:
27.04.2005

Schleswig-Holstein
Socket verschluckt Daten :(Nach oben.
Hallo zusammen,

ich versuche gerade den Netzwerkteil des Buches "3D-Spieleprogrammierung" nach zu programmieren. Allerdings übernehme ich den Quellcode nicht 1:1, sondern habe es etwas abgeändert, damit ich den Code später auf Linux portieren kann (Zu Lernzwecken).

Nun habe ich das Problem, dass das Socket Daten verschluckt, wenn Server und Client nicht auf der gleichen Maschine sind.

Wenn ich in einer Schleife ca. 1000 Pakete senden will, dann kommen ca die Hälfte an. Nur wenn ich in der Schleife ein Sleep(1) schreibe, dann erhöht sich die Anzahl, aber leider auch die Zeit, die benötigt wird die Pakete zu senden.
Es dauert ca 16 Sekunden und das empfinde ich als zu hoch.

Vielleicht hat jemand Lust mal auf den Code zu schauen. Da ich nicht weiss, welcher Teil diesen Fehler verursacht, poste ich Ihn mal komplett.

Code:
/////////////////////////////////////////////////////////////////////////////
// File      : CSocket.h
// Brief     : Testklasse fuer eine Socketimplementierung
// Created     : 29.12.2008
/////////////////////////////////////////////////////////////////////////////

#ifndef _CSOCKET_H_
#define _CSOCKET_H_

//Includes und libs
#include 
#include 

#pragma comment (lib, \"Ws2_32.lib\")

//Reservierte Nachrichtentypen
enum packagetype_e
{
    TYPE_NEWID,        //Neuer Client bekommt eine ID
    TYPE_NEWCLIENT, //Broadcast an Clients, dass sich ein Client angemeldet hat
    TYPE_REMCLIENT, //Broadcast an Clients, dass sich ein Client abgemeldet hat

    TYPE_CHAR = 50    //Chat Nachricht (Testweise)
};

//Datenpaket
typedef struct netpackage_type
{
    UINT nType;          //Nachrichtentyp
    UINT nSender;      //Absender (0 bedeutet Server)
    UINT nRecipient;  //Empfaenger (0 bedeutet Server, 1 bedeutet alle Clients)

    UINT nDataLength; //Datenlaenge von lpData in Bytes
    void *lpData;      //Zu sendende Daten
} netpackage_t;

//Clients
typedef struct clients_type
{
    UINT    nID;        //ID des Clients
    SOCKET    nSocket;    //Socket vom Client
    char    szIP[256];    //IP-Adresse
    ULONG    nConnected;    //Timestamp der Verbindung
} client_t;

//Socket Klasse
class CSocket
{

private:
    SOCKET  m_nSocket;            //Socket
    UINT    m_nPort;            //Port
    UINT    m_nPackets;            //Anzahl der wartenden Pakete
    UINT    m_nRec;                //Anzahl der Receives
    UINT    m_nMaxSize;            //Maximale Sendegroesse inkl. Header
    FD_SET  m_FdSet;            //Socket Array (http://www.c-worker.ch/tuts/select.php)
    char   *m_cBuffer;//[65536];    //Empfangspuffer
    char   *m_lpSendBuffer;        //Sendepuffer

    //Clients
    std::vector m_vClients;

    //Einen Client akzeptieren
    bool Accept();

    //Daten empfangen
    bool Receive(const client_t *lpClient);

    //Schreibe den letzen WSA Error
    void LogLastError(const char *szFunction);

public:
    CSocket();
    ~CSocket();

    //Socket Initialisierung
    bool CreateSocket();

    //Socket an einen Port und eine Schnittstelle binden. Wird NULL uebergeben
    //so wird INADDR_ANY benutzt.
    bool BindSocket(UINT nPort, const char *szSocketAddress = NULL);

    //Serverfunktion aktivieren
    bool Listen();

    //Zu einem Server verbinden
    bool Connect(const char *szServer, UINT nServerPort);

    //Daten senden. Diese Funktion wird vom Client und von dem Server benutzt.
    //Der Server muss zusaetzlich den Socket angeben. Clients koennen diesen
    //Parameter ingnorieren.
    bool Send(const char *szData, UINT nSize, SOCKET nReceiver = 0);
    bool Send(const netpackage_t *lpPackage, SOCKET nReceiver = 0);

    bool Disconnect();

    bool IsConnected();

    //Anzahl der verbundenen Clients zureuckgeben
    int GetConnectedClients();

    //TEST
    bool Loop();

};



#endif //_CSOCKET_H_


Code:
/////////////////////////////////////////////////////////////////////////////
// File      : CSocket.cpp
// Brief     : Testklasse fuer eine Socketimplementierung
// Created     : 29.12.2008
/////////////////////////////////////////////////////////////////////////////

#include \"CSocket.h\"
#include 

CSocket::CSocket()
{
    m_nSocket  = INVALID_SOCKET;
    m_nPort    = 0;
    m_nPackets = 0;
    m_nRec       = 0;
    m_nMaxSize = 65536;
    m_cBuffer  = NULL;

    m_lpSendBuffer = new char[m_nMaxSize];
}

CSocket::~CSocket()
{
    //Socket schliessen, falls dieser noch gueltig ist
    if (m_nSocket != INVALID_SOCKET)
        Disconnect();

    //Aufraeumen
    WSACleanup();

    delete [] m_lpSendBuffer;
}

//Einen Client akzeptieren
bool CSocket::Accept()
{
    sockaddr_in saClientAddress;
    int            nClientSize;
    client_t    client;

    //Client akzeptieren
    nClientSize= sizeof(sockaddr_in);
    client.nSocket = accept(m_nSocket, (SOCKADDR*)&saClientAddress, &nClientSize);

    //Erfolgreich ?
    if (client.nSocket == INVALID_SOCKET)
    {
        LogLastError(\"Accept\");
        return false;
    }

    //Informationen abfragen
    SOCKADDR_IN sai; 

    int sai_len = sizeof( SOCKADDR_IN ); 
        memset( &sai, 0, sizeof( SOCKADDR_IN ) ); 
        getpeername( client.nSocket, (SOCKADDR*)&sai, &sai_len ); 

    strcpy(client.szIP , inet_ntoa( sai.sin_addr ) ); 

    printf(\"New Client : %s\n\", client.szIP);

    //Client hinzufuegen
    m_vClients.push_back(client);

    return true;
}

//Daten empfangen
bool CSocket::Receive(const client_t *lpClient)
{
    UINT nSize    = 65536;    //Maximale Bytes pro Durchlauf
    UINT nRead    = 0;        //Anzahl gelesene Bytes
    UINT nSeek    = 0;        //Position im Buffer
    UINT nLeft    = 0;        //Verbleibende Bytes
    bool bDone    = false;    //True, wenn fertig
    bool bFirst = true;        //True beim dem ersten Schleifendurchlauf

    m_cBuffer = new char[nSize];

    //Zeiger auf Netzwerkpaket
    netpackage_t *lpPackage = NULL;

    //Totale groesse des Paketes
    UINT nPackageSize        = 0;

    //Groesse eines Header
    UINT nDefPackageSize    = sizeof(netpackage_t);

    //Debug
    m_nRec++;
    printf(\"Empfange Daten (%d) von %s\n\", m_nRec, lpClient->szIP);

    //Bei jedem Schleifendurchlauf nSize Bytes Daten lesen, bis
    //keine mehr vorhanden sind
    while (!bDone)
    {
        nRead = recv(lpClient->nSocket, &m_cBuffer[nLeft], nSize - nLeft, 0);

        //Client weg ?
        if (bFirst)
        {
            if (nRead == 0)
                return false;

            bFirst = false;
        }

        //Fehler ?
        if (nRead == SOCKET_ERROR)
        {
            int nError = WSAGetLastError();

            //Kritischer Fehler ?
            if ((nError != WSAEMSGSIZE) && (nError != WSAEWOULDBLOCK))
            {
                bDone = true;

                printf (\"\a\a\aAchtung Komischer Fehler !\n\");
                return false;
            }
        }

        //Nun sind nRead Bytes im Buffer
        if (nRead <= 0)
            bDone = true;
        else
        {
            //Alte Daten im Buffer beachten
            nRead += nLeft;

            //Loopen, bis wir einen kompletten Header finden
            while ((nRead - nSeek) >= nDefPackageSize) // Ergaenzt : '='
            {
                //Naechstes Datenstueck
                lpPackage    = (netpackage_t*)&m_cBuffer[nSeek];
                lpPackage->lpData = &m_cBuffer[nSeek] + nDefPackageSize;
                nPackageSize = nDefPackageSize + lpPackage->nDataLength;

                //Haben wir das ganze Datenpaket empfangen ?
                if ((nRead - nSeek) >= nPackageSize)
                {
                    

                    //TODO : Enqueue Message
                    //printf(\"\r#%d    \", m_nPackets);

                    if (lpPackage->nType == TYPE_CHAR)
                    {

                        m_nPackets++;

                        printf(\"ID : %d - # : %d) : %s\n\", lpPackage->nSender, m_nPackets, lpPackage->lpData);
                        std::cout << m_cBuffer << std::endl;
                    }
                    else
                    {
                        //m_nPackets--;

                        printf(\"Paket #%d Fehlerhaft.\n\", m_nPackets);
                    }

                    nSeek += nPackageSize;
                }
                else
                {
                    //Das Bruchstueck an den Anfang des Buffers kopieren und weiterlesen
                    memcpy(m_cBuffer, &m_cBuffer[nSeek], nRead - nSeek);
                    nLeft = nRead - nSeek;

                    break;
                }
            }

            //Haben wir alle Daten ?
            if (nRead <= nSize) //Ergaenzt : '='
                bDone = true;

        }
    }//while

    //printf(\"[%d] %s\n\", m_nPackets, m_cBuffer);

    Sleep(1);

    delete [] m_cBuffer;

    return true;
}
    

//Schreibe den letzten WSA Error
void CSocket::LogLastError(const char *szFunction)
{
    UINT nLastError = WSAGetLastError();

    if (nLastError == 0)
        return;

    std::cout << \"Socket Error : [\" << szFunction << \"] \";

    switch (nLastError)
    {
        case WSANOTINITIALISED:
            std::cout << \"Successful WSAStartup not yet performed.\" << std::endl;
            break;

        case WSAEADDRNOTAVAIL:
            std::cout << \"Cannot assign requested address. The requested address is not valid on this local computer.\" << std::endl;
            break;

        case WSAHOST_NOT_FOUND:
            std::cout << \"Host not found.\" << std::endl;
            break;

        case WSAECONNREFUSED:
            std::cout << \"Connection refused.\" << std::endl;
            break;

        default:
            std::cout << \"Unknown WSA Error #\" << nLastError << std::endl;
            break;
    }
}

//Socket erzeugen
bool CSocket::CreateSocket()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int nError;    

    //WSA Starten
    wVersionRequested = MAKEWORD(2, 2);
    nError = WSAStartup(wVersionRequested, &wsaData);

    if (nError != 0)
    {
        LogLastError(\"CreateSocket() WSAStartup\");
        return false;
    }

    //Existiert bereits ein Socket ?
    if (m_nSocket != INVALID_SOCKET)
        if (Disconnect() == false)
            return false;

    //Socket erstellen
    m_nSocket = socket(AF_INET, SOCK_STREAM, 0);

    //Erfolgreich ?
    if (m_nSocket == INVALID_SOCKET)
    {
        LogLastError(\"CreateSocket() socket(AF_INET, SOCK_STREAM, 0)\");
        return false;
    }

    return true;
}

//Socket an einen Port und eine Schnittstelle binden. Wird NULL uebergeben
//so wird INADDR_ANY benutzt.
bool CSocket::BindSocket(UINT nPort, const char *szSocketAddress)
{
    sockaddr_in saServerAddress;

    memset(&saServerAddress, 0, sizeof(sockaddr_in));
    
    saServerAddress.sin_family        = AF_INET;

    if (szSocketAddress != NULL)
        saServerAddress.sin_addr.s_addr = inet_addr(szSocketAddress);
    else
        saServerAddress.sin_addr.s_addr = INADDR_ANY;//inet_addr(\"127.0.0.1\");

    saServerAddress.sin_port        = htons(nPort);

    //Socket binden
    if (bind(m_nSocket, (SOCKADDR*)&saServerAddress, sizeof(saServerAddress)) == SOCKET_ERROR)
    {
        LogLastError(\"BindSocket()\");
        Disconnect();

        return false;
    }

    return true;
}

//Socket in den Listen-Modus setzen
bool CSocket::Listen()
{
    if (listen(m_nSocket, 64) != 0)
    {
        LogLastError(\"Listen()\");
        return false;
    }

    return true;
}

//Zu einem Server verbinden
bool CSocket::Connect(const char *szServer, UINT nServerPort)
{
    sockaddr_in saServerAddress;
    LPHOSTENT    lpHost = NULL;

    //Es wird versucht den Server zu finden
    memset(&saServerAddress, 0, sizeof(sockaddr_in));

    saServerAddress.sin_port = htons(nServerPort);
    saServerAddress.sin_family = AF_INET;
    saServerAddress.sin_addr.S_un.S_addr = inet_addr(szServer);

    //Falls ein Name und keine IP uebergeben wurde, wird versucht
    //diesen aufzuloesen.
    if (saServerAddress.sin_addr.S_un.S_addr == INADDR_NONE)
    {
        lpHost = gethostbyname(szServer);

        if (lpHost != NULL)
            saServerAddress.sin_addr.S_un.S_addr = ((LPIN_ADDR)lpHost->h_addr)->S_un.S_addr;
        else
        {
            LogLastError(\"gethostbyname()\");
            return false;
        }

    }

    //Zum Server verbinden
    if (connect(m_nSocket, (SOCKADDR*)&saServerAddress, sizeof(sockaddr)) == SOCKET_ERROR)
    {
        LogLastError(\"connect()\");

        Disconnect();
        return false;
    }

    //TODO : Erfolgreichen Verbindungsstatus setzen

    return true;
}

//Daten senden. Diese Funktion wird vom Client und von dem Server benutzt.
//Der Server muss zusaetzlich den Socket angeben. Clients koennen diesen
//Parameter ingnorieren.
bool CSocket::Send(const char *szData, UINT nSize, SOCKET nReceiver)
{
    UINT nSend = 0;
    UINT nLeft = 0;

    if (nReceiver == 0)
        nReceiver = m_nSocket;

    while (nSend < nSize)
    {
        nLeft = send(nReceiver, szData + nSend, nSize - nSend, 0);

        //Erfolgreich ?
        if (nLeft == SOCKET_ERROR)
        {
            LogLastError(\"send()\");

            return false;
        }

        if (nLeft == nSize)
            break;

        printf(\"nLeft = %d\n\", nLeft);

        nSend += nLeft;
    }

    return true;
}

bool CSocket::Send(const netpackage_t *lpPackage, SOCKET nReceiver)
{
    UINT nSizeTotal = sizeof(netpackage_t) + lpPackage->nDataLength;
    //char *lpBuffer = new char[m_nMaxSize]; //TODO : Eventuell als Member ?

    //Daten-Serialisierung
    memcpy(m_lpSendBuffer, lpPackage, sizeof(netpackage_t));
    memcpy(m_lpSendBuffer + sizeof(netpackage_t), lpPackage->lpData, lpPackage->nDataLength);

    //Daten Senden
    Send(m_lpSendBuffer, nSizeTotal, nReceiver);

    return true;
}

//Socket herunterfahren und schliessen
bool CSocket::Disconnect()
{
    if (m_nSocket == INVALID_SOCKET)
        return true;

    //Socket runterfahren
    shutdown(m_nSocket, SD_BOTH);
    
    //Socket schliessen
    closesocket(m_nSocket);

    m_nSocket = INVALID_SOCKET;

    return true;
}

//Anzahl der verbundenen Clients zureuckgeben
int CSocket::GetConnectedClients()
{
    return m_vClients.size();
}

//TEST
bool CSocket::Loop()
{
    int nSocketState;

    // Inhalt vom FD_SET leeren
    FD_ZERO(&m_FdSet); 

    //Den Accept-Socket hinzufuegen
    FD_SET(m_nSocket, &m_FdSet); 

    //Hier werden alle gueltigen Client Sockets dem FD_SET hinzugefuegt werden
    for (std::vector::iterator it = m_vClients.begin(); it != m_vClients.end(); ++it)
    {
        //std::cout << \"Client im Vector : \" << it->szIP << std::endl;

        if (it->nSocket != INVALID_SOCKET)
            FD_SET(it->nSocket, &m_FdSet);
    }


    //Nun wird geschaut, welche Sockets Daten bereitstellen (oder accept() beim Server Socket)
    //Alle Clients, welche keine Daten haben, werden aus diesem Array entfernt.
    nSocketState = select(0, &m_FdSet, NULL, NULL, NULL);

    //Erfolgreich ?
    if (nSocketState == INVALID_SOCKET)
    {
        LogLastError(\"select()\");
        return false;
    }

    //Wird auf eine neue Verbindung gewartet ?
    if(FD_ISSET(m_nSocket, &m_FdSet)) 
        Accept();

    //Die Clients werden durchlaufen und mit den empfangsbereiten Sockets verglichen.
    //Bei einer uebereinstimmung werden die Daten empfangen
    for (std::vector::iterator it = m_vClients.begin(); it != m_vClients.end(); ++it)
        if (FD_ISSET(it->nSocket, &m_FdSet))
        {
            if (!Receive(&*(it)))
            {
                printf(\"Entferne Client.\n\"); //TODO : Wenn false, client entfernen und socket schliessen

                //Test
                m_vClients.erase(it);
                break;
            }
        }

    return false;
}


Code:
/////////////////////////////////////////////////////////////////////////////
// File      : main.h
// Brief     :
// Created     : 29.12.2008
/////////////////////////////////////////////////////////////////////////////

#ifndef _MAIN_H_
#define _MAIN_H_

#include \"CSocket.h\"

//Prototypen
bool ConnectToServer(const char *szServer, UINT nPort);
bool CreateServer(UINT nPort);


#endif //_MAIN_H_


Code:
/////////////////////////////////////////////////////////////////////////////
// File      : main.cpp
// Brief     :
// Created     : 29.12.2008
/////////////////////////////////////////////////////////////////////////////

#include \"main.h\"
#include 

using namespace std;

int main(int argc, char *argv)
{
    char cChoice = 0;

    cout << \"Socket Testprogramm\" << endl
         << \"================================================\" << endl << endl
         << \"Moechten Sie einen Server (s) oder einen Client (c) starten ? (q) fuer Quit :\" << endl << endl;

    do
    {
        cout << \"Auswahl : \";
        cin >> cChoice;
        cin.clear();
        cin.sync();

        if (cChoice == 's')
        {
            CreateServer(42202);

            return 0;
        }

        if (cChoice == 'c')
        {
            ConnectToServer(\"127.0.0.1\", 42202);

            return 0;
        }

    } while(cChoice != 'q');


    return 0;
}

bool ConnectToServer(const char *szServer, UINT nPort)
{
    CSocket Socket;

    //CreateSocket()
    cout << \"Erstelle Socket ... \";

    if (Socket.CreateSocket())
        cout << \"Erfolgreich !\" << endl;
    else
    {
        cout << \"Fehlgeschlagen !\" << endl;

        return false;
    }

    //Verbinde zum Server
    //CreateSocket()
    cout << \"Verbinde zum Server [\" << szServer << \":\" << nPort << \"] ... \";

    if (Socket.Connect(szServer, nPort))
        cout << \"Erfolgreich !\" << endl;
    else
    {
        cout << \"Fehlgeschlagen !\" << endl;

        return false;
    }

    //Testpaket
    netpackage_t package;

    char szMessage[256] = \"Hallo Welt, wie geht es Dir denn heute so :)\";
    package.lpData = new char[1024];

    package.nType        = TYPE_CHAR;
    package.nSender        = 1;
    package.nRecipient    = 0;
    package.nDataLength = sizeof(szMessage);
    memcpy(package.lpData, szMessage, sizeof(szMessage)+1);

    cout << \"Sende Daten ... \" << endl;

    //Testpaket senden
    for (int nIndex = 0; nIndex != 1000; nIndex++)
    {
        printf(\"\r#%d\", nIndex);
        package.nSender = nIndex;
        Socket.Send(&package);
        Sleep(1);
    }

    delete [] package.lpData;

    cout << \"Alle Daten gesendet !\" << endl;

    return true;
}

bool CreateServer(UINT nPort)
{
    CSocket Socket;

    nPort = 42202;

    //CreateSocket()
    cout << \"Erstelle Socket ... \";

    if (Socket.CreateSocket())
        cout << \"Erfolgreich !\" << endl;
    else
        cout << \"Fehlgeschlagen !\" << endl;

    //BindSocket()
    cout << \"Binde Socket an Port #\" << nPort << \" ... \";

    if (Socket.BindSocket(nPort))
        cout << \"Erfolgreich !\" << endl;
    else
        cout << \"Fehlgeschlagen !\" << endl;

    //Listen()
    cout << \"Setze Socket in en Listen-Modus ... \";

    if (Socket.Listen())
        cout << \"Erfolgreich !\" << endl;
    else
        cout << \"Fehlgeschlagen !\" << endl;

    //Loop
    while (true)
    {
        Socket.Loop();

        //Sleep(1);
    }

    return true;
}
30.12.2008, 16:40:04 Uhr
Löwe Offline
ZFX'ler


Registriert seit:
29.09.2003

Nordrhein-Westfalen
Re: Socket verschluckt Daten :(Nach oben.
ich muss gestehen, ich hab mir den code nicht angesehen. auch weil ich seit jahren nicht wirklich programmiert habe und gerade wieder ein wenig anfange .

aber, ich gehe mal davon aus, das z.b. der server nicht wartet, bis der client den empfang des letzten packetes bestätigt hat, bis er das nächste sendet, oder?

nach meiner erfahrung wäre das aber die einige mir bekannte lösung.

also:
server schick daten an client. client schickt empfangsbestätigung an server. server schickt nächste daten. client schickt empfangsbestätigung. ...

mfg
Löwe
30.12.2008, 19:02:37 Uhr
Godhand Offline
ZFX'ler


Registriert seit:
15.10.2002

Deutschland
Re: Socket verschluckt Daten :(Nach oben.
Hi,

Zitat:
aber, ich gehe mal davon aus, das z.b. der server nicht wartet, bis der client den empfang des letzten packetes bestätigt hat, bis er das nächste sendet, oder?


Das ist auch gut so. Ansonsten würde das Konzept des Sendefensters einfach nur absurd werden.

Zitat:

nach meiner erfahrung wäre das aber die einige mir bekannte lösung.


Quark.

Zitat:

server schick daten an client. client schickt empfangsbestätigung an server. server schickt nächste daten. client schickt empfangsbestätigung. ...


Ja, wenn man das so machen würde, käme man wirklich nicht über Schildkrötengeschwindigkeit hinaus.

Also generell: TCP kümmert sich um den ganzen Kram mit Sende- und Empfangsfensterns, Bestätigungen, drohenden Overflows bei Empfangsbuffern, etc. Der Empfänger teilt ja schließlich dem Sender durch das TCP-Protokoll mit, wieviele Daten er zu senden hat.

Zu Löwe:
Entrümpel mal deinen Code, der ist mir wirklich zu lang, um da durchzusteigen.

Edit: Warum ist der erste Parameter von select 0?

Edit 2: Füg mal beim select ein paar mehr Fehlerüberprüfungen ein.


5 Mal gendert, zuletzt am 31.12.2008, 13:01:11 Uhr von Godhand.
31.12.2008, 12:36:52 Uhr
DarkD Offline
ZFX'ler


Registriert seit:
30.03.2005

Nordrhein-Westfalen
Re: Socket verschluckt Daten :(Nach oben.
Überprüf doch mal was send() zurückliefert. Vielleicht werden ja nur die Hälfte der Daten wirklich gesendet.

Code:
nLeft = send(nReceiver, szData + nSend, nSize - nSend, 0);

if (nLeft <  nSize - nSend)
{
LogLastError(\"send2()\");
return false;
}


Ich hab mir den Code auch nicht im Detail angeguckt, aber das ist so die Erfahrung die ich mit Winsock habe.

Zitat:

Edit: Warum ist der erste Parameter von select 0?


Laut MSDN:

Zitat:

Ignored. The nfds parameter is included only for compatibility with Berkeley sockets.


Kann also wohl auf 0 gelassen werden.

1 Mal gendert, zuletzt am 31.12.2008, 14:19:31 Uhr von DarkD.
31.12.2008, 14:16:15 Uhr
Normal


ZFX Community Software, Version 0.9.1
Copyright 2002-2003 by Steffen Engel