Toon posts:

[C++][Win32] Winsock, probleem sluiten socket.

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,

Ik ben een programma aan het maken wat een web-pagina inleest, data eruit haalt en de boel verwerkt. Ik maak geen gebruik van MFC, puur Win32 API. Nu komt er allemaal data binnen via FD_READ, dat lees ik en stop ik in een file. Er komt ook een FD_CLOSE binnen als alle data is ontvangen.

Het probleem is dat ik een FD_CLOSE ontvang, de socket sluit... maar dat er vervolgens nog een paar FD_READ messages binnen komen.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
        /**
         * WSAAsyncSelect, er komt een bericht binnen van de socket.
         */
    case CM_READ_SOCKET:
        {
            switch(lParam) {
            case FD_READ:
                {   
                    if(recFlag & FLAG_OVERVIEW) {
                        char szData[512]; DWORD dwBytesWritten;
                        int ret = recv(hSocket, szData, sizeof(szData), 0);
                        if(ret == SOCKET_ERROR) {
                            ret = WSAGetLastError();
                            if(ret == WSAEWOULDBLOCK)
                                return 0;       // Gewoon doorgaan.
                            sprintf(szBuffer, "Fout tijdens het ontvangen van data!\nFout code: %i", ret);
                            MessageBox(hWnd, szBuffer, "Fout!", MB_OK);
                            return 0;
                        }
                        else if(ret == 0) {
                            recFlag = recFlag & (~FLAG_OVERVIEW);
                            CloseHandle(receivedData);
                            return 0;
                        }
                        szData[ret] = 0;

                        SetFilePointer(receivedData, 0, NULL, FILE_END);
                        WriteFile(receivedData, szData, strlen(szData), &dwBytesWritten, NULL);
                    }
                    if(recFlag & FLAG_PRODUCTION) {
                        char szData[512]; DWORD dwBytesWritten;
                        int ret = recv(hSocket, szData, sizeof(szData), 0);
                        if(ret == SOCKET_ERROR) {
                            ret = WSAGetLastError();
                            if(ret == WSAEWOULDBLOCK)
                                return 0;       // Gewoon doorgaan.
                            sprintf(szBuffer, "Fout tijdens het ontvangen van data!\nFout code: %i", ret);
                            MessageBox(hWnd, szBuffer, "Fout!", MB_OK);
                            return 0;
                        }
                        else if(ret == 0) {
                            recFlag = recFlag & (~FLAG_PRODUCTION);
                            CloseHandle(receivedData);
                            return 0;
                        }
                        szData[ret] = 0;

                        SetFilePointer(receivedData, 0, NULL, FILE_END);
                        WriteFile(receivedData, szData, strlen(szData), &dwBytesWritten, NULL);
                    } 
                }break;
            case FD_CLOSE:
                {
                    closesocket(hSocket);
                }break;
            }
        }break;


Nu heb ik geprobeerd om niet de socket te sluiten maar te wachten totdat er aan deze voorwaarde wordt voldaan:

C++:
1
2
3
4
5
                        else if(ret == 0) {
                            recFlag = recFlag & (~FLAG_OVERVIEW);
                            CloseHandle(receivedData);
                            return 0;
                        }


Dat gebeurt dus niet omdat de socket niet wordt gesloten tijdens het lezen (gok ik).

Ik heb ook geprobeerd om als de FD_CLOSE wordt aangeroepen alle data wat nog ontvangen moet worden binnen te halen. Maar dan heb ik een probleem dat er vervolgens weer een paar FD_READ messages worden afgehandeld, dat probleem is te verhelpen om een boolean waarde te zetten bSocketClosed, maar ik denk dat dat niet helemaal juist is.

Ik weet niet precies wat nou een goede oplossing is. Het probleem is dat het niet lukt om alle data te ontvangen, en wanneer dat gelukt is de socket en file-handle te sluiten.

Ik hoop dat het duidelijk genoeg is,

Peter.

Verwijderd

Topicstarter
Ik heb het nog steeds niet helemaal opgelost. Nu ben ik gewoon alle data gaan inlezen als ik een FD_CLOSE ontvang maar dat moet eigenlijk niet want dan ga je eigenlijk terug naar blocking-sockets. Ik wil gewoon pas de FD_CLOSE afhandlen zodra alle data ontvangen is.

[ Voor 36% gewijzigd door Verwijderd op 16-07-2006 23:12 ]


  • TheBlasphemer
  • Registratie: September 2004
  • Laatst online: 13-11-2025
Ik kan je zo snel niet echt helpen met de sockets, ikzelf gebruik al jaren gewoon lekker select in een aparte thread, maar ik vroeg me wel het volgende af:
Waarom sockets als Win32 een prima library heeft voor het ophalen van webpaginas?
Bijkomend voordeel is dan ook dat je je geen zorgen hoeft te maken over proxies e.d. van de eindgebruiker, aangezien WinInet dat dan voor je regelt...

Zoek eens op InternetOpen in de MSDN/Platform SDK zou ik zeggen :)

[img=http://www.web2messenger.com/smallstatus/w2m/theblasp.png]


Verwijderd

Topicstarter
Verhip, daar zeg je iets heel slims. Ben ik even onhandig bezig, ik schrijf toch geen eigen webbrowser dus dat zou heel goed goed bruikbaar zijn. Ik heb ooit wel eens een functie voorbij zien schieten als URLDownloadToFile of iets dergelijks, ik zal er vanmiddag eens mee prutsen.

Bedankt.

*Misschien weet nog wel iemand wat ik fout doe, zou namelijk wel graag het probleem willen oplossen :).

  • quistnet
  • Registratie: Januari 2001
  • Laatst online: 18-09-2020
Is het niet zo dat de FD_CLOSE alleen is om je te notificeren dat de tegenpartij de socket heeft afgesloten en er sowieso geen communicatie meer kan of zal plaatsvinden? zelfs de closesocket is dan enkel een formaliteit volgens mij...

Maar belangrijker is:

Waarom lees je maar maximaal 512 bytes in bij zo'n read event?
Lijkt me dat er veel meer in zo'n socketbuffer kan zitten... Moet je niet iets van een while ( nogsteedsdatainbuffer ) { recv() etc }

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Although WSAAsyncSelect immediately disables event message posting for the socket in this instance, it is possible that messages could be waiting in the application's message queue. Therefore, the application must be prepared to receive network event messages even after cancellation. Closing a socket with closesocket also cancels WSAAsyncSelect message sending, but the same caveat about messages in the queue still applies.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Maar dan is het dus heel normaal om gewoon in een loopje al je data op te halen als FD_CLOSE is aangeroepen, ik dacht dat het namelijk een beetje vreemd was... een WSAEWOULDBLOCK message wordt dan ook genegeerd. De loop gaat door tot alles binnen is.
Waarom lees je maar maximaal 512 bytes in bij zo'n read event?
Lijkt me dat er veel meer in zo'n socketbuffer kan zitten... Moet je niet iets van een while ( nogsteedsdatainbuffer ) { recv() etc }
Als ik in MSDN kijk zie ik dat er FD_READ messages verzonden blijven worden als de data nog niet helemaal ontvangen is, stel het is een abnormaal grote pagina... en ik ontvang mijn data op jouw manier, dan blijft m'n applicatie hangen (niet dat ik met zo'n pagina te doen krijg, maar in theorie is het mogelijk).

[ Voor 48% gewijzigd door Verwijderd op 17-07-2006 14:27 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15-02 11:20
Verwijderd schreef op maandag 17 juli 2006 @ 14:24:
Als ik in MSDN kijk zie ik dat er FD_READ messages verzonden blijven worden als de data nog niet helemaal ontvangen is, stel het is een abnormaal grote pagina... en ik ontvang mijn data op jouw manier, dan blijft m'n applicatie hangen (niet dat ik met zo'n pagina te doen krijg, maar in theorie is het mogelijk).
Als je niet sneller data uit de queue kan halen dan 'het netwerk' ze erin stopt heb je een probleem :) Er kan geen sprake van zijn dat je programma blijft hangen in de situatie die je schetst.

[ Voor 5% gewijzigd door farlane op 19-07-2006 01:18 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

Topicstarter
Ik had ook gezien dat ik hier en daar wat verkeerd deed. Ik ga de boel opnieuw programmeren en goed elke stap doornemen.

Ik heb namelijk een voorbeeldje gezien en die houd helemaal geen rekening met eventuele achtergebleven data bij het sluiten van de socket terwijl wel alle data wordt ontvangen... progsel is een paar duizend lijnen groot dus moet nog even spitten :).
Pagina: 1