Toon posts:

[C++] TCP socket disconnect afhandelen

Pagina: 1
Acties:

Onderwerpen


  • Bolk
  • Registratie: februari 2001
  • Niet online

Bolk

Change the equation.

Topicstarter
Hoi!

Voordat iedereen me uitlacht om onderstaande code (:P); ik ben over het algemeen meer PHP-er met een beetje C# kennis (lerende) maar in verband met een game-plugin word ik geforceerd aan de C++ gezet ;) Ik loop tegen een probleem aan en ik kom er niet aan uit.

Situatie
Voor een racespel heb ik een SDK gedownload waarin ze voorbeeldcode geven van een plugin. De plugin geeft mij iedere halve seconde kant en klare data uit de game via een struct. Ik kan dit wegschrijven in een file en dan weer uitlezen wat ik vroeger gedaan heb, maar wil nu het met een socket server oplossen. Met hier en daar wat hulp en veel gegoogle heb ik een basic socket server die het prima doet. Totdat ik erachter kwam dat een bokkende verbinding nog wel eens roet in het eten kan gooien. Het is de bedoeling dat dit 24/7 gaat draaien, zodat er realtime data op een website gepubliceerd kan worden.

De plugin dient als een server en met een C# app als client stuur ik iedere seconde data naar de server (connectie blijft dus continu open staan) en krijg zo m'n data uit de game en verwerk ik het verder met C#.

De server in de plugin draait in een aparte thread.

Probleem
Als de connectie correct wordt afgesloten (dus via C# met een socket close) dan wordt de thread van de server gemarkeerd als finished. De thread wordt dan via de workerthread in de plugin zelf (van de game) weer herstart. Dit werkt allemaal prima.

Het gaat mis wanneer er een verbinding wegvalt. Denk hierbij aan een internet connectie of als ik de kabel eruit trek. Op een of andere manier breaked-ie niet uit de onderstaande while loop:


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
58
59
60
61
62
63
64
65
66
67
68
69
DWORD WINAPI Checker(void *)
{
    WSADATA wsaData;
    sockaddr_in local;
    int wsaret = WSAStartup(0x101, &wsaData);
    char buf[2];
    SOCKET client;
    sockaddr_in from;
    int fromlen;

    int nret;

    local.sin_family=AF_INET;
    local.sin_addr.s_addr=INADDR_ANY;
    local.sin_port=htons(atoi(port));

    server=socket(AF_INET,SOCK_STREAM,0);
    nret = bind(server,(sockaddr*)&local,sizeof(local));

    if (nret == SOCKET_ERROR)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR Bind", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    nret = listen(server, 1);
    
    if (nret == SOCKET_ERROR)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR Listen", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    fromlen = sizeof(from);

    client = accept(server, (struct sockaddr*)&from,&fromlen);

    if(client == INVALID_SOCKET)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR Accept", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    while(client != INVALID_SOCKET && recv(client, buf, 2, 0) != SOCKET_ERROR)
    {
        memset(&OurInfo, '\0', sizeof(OurInfo));

        // Print general scoring info
        //[*KNIP*] Hier maak ik de data op die ik wil gaan verzenden

        if(send(client, OurInfo, strlen(OurInfo), 0) == SOCKET_ERROR) break;
    }

    closesocket(client);
    closesocket(server);
    WSACleanup();
    
    serverAlive = false;
    
    //MessageBox(NULL, "Thread should close here...", "socketIndication", MB_OK);

    return 0;
}


Kan iemand mij vertellen hoe ik een disconnect het beste kan detecteren? Wanneer de connectie wegvalt dan blijft, volgens netstat -an, de verbinding op ESTABLISHED staan. Logisch, want op een of andere manier kom ik niet uit die while loop. Ik krijg dan de volgende error voor m'n kiezen van m'n C# client app:

An existing connection was forcibly closed by the remote host

Wat volgens dit betekent dat een connectie wel gemaakt wordt, maar dat er geen data verzonden kan worden door dat er geen accept plaats vindt?

Ik heb overwogen om over te stappen naar UDP en ook om iedere keer de connectie af te sluiten en weer opnieuw op te bouwen (dus zonder de while loop), want eigenlijk betekent dat ik iedere seconde een nieuwe thread (+ socket server) aan moet maken.

Voordat ik dat soort truukjes ga uithalen wilde ik liever het eerst hier vragen. Hoop dat iemand me kan helpen :)

Ik bespeur hier een zekere mate van onethische logica.


  • Bolk
  • Registratie: februari 2001
  • Niet online

Bolk

Change the equation.

Topicstarter
Time out ligt natuurlijk redelijk voor de hand. Dat ik daar niet eerder aan gedacht heb! Thanks!

De server heeft maar 1 connectie. Ik hoef daarom niet aan de gang met asynchrone threads etc.

Ik heb nu met setsockopt zowel de send- als receivetimeouts gezet op 10 seconden. Eens kijken of dit de oplossing is...

Ik bespeur hier een zekere mate van onethische logica.


  • Bolk
  • Registratie: februari 2001
  • Niet online

Bolk

Change the equation.

Topicstarter
farlane schreef op dinsdag 05 oktober 2010 @ 19:09:
[...]

BTW, ga je zelf ook nog tips/oplosssingen geven aan de TS of blijf je zo doordrammen?
Ik vind de discussie anders best aardig. Aangezien ik ook UDP overwogen heb.

Anyway.. Met gepaste trots (*D) kan ik melden dat er nu keurig een restart optreedt na het toevoegen van de timeouts. Hier en daar nog wat vage errors maar die kan ik vast wel afvangen en waar nodig oplossen.

Bedankt iedereen!

Voor de search evt:

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
DWORD WINAPI Checker(void *)
{
    WSADATA wsaData;
    sockaddr_in local;
    int wsaret = WSAStartup(0x101, &wsaData);
    char buf[2];
    SOCKET client;
    sockaddr_in from;
    int fromlen, optval;

    int nret;

    local.sin_family=AF_INET;
    local.sin_addr.s_addr=INADDR_ANY;
    local.sin_port=htons(atoi(port));

    server = socket(AF_INET, SOCK_STREAM, 0);
    nret = bind(server, (sockaddr*)&local, sizeof(local));

    if (nret == SOCKET_ERROR)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR Bind", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    optval = 10000;   // time out on recv
    nret = setsockopt(server, SOL_SOCKET, SO_RCVTIMEO, (char *)&optval, 4);

    if (nret == SOCKET_ERROR)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR SO_RCVTIMEO", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    optval = 10000;   // time out on send
    nret = setsockopt(server, SOL_SOCKET, SO_SNDTIMEO, (char *)&optval, 4);
    if (nret == SOCKET_ERROR)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR SO_SNDTIMEO", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    nret = listen(server, 1);
    
    if (nret == SOCKET_ERROR)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR Listen", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    fromlen = sizeof(from);

    client = accept(server, (struct sockaddr*)&from,&fromlen);

    if(client == INVALID_SOCKET)
    {
        nret = WSAGetLastError();
        //MessageBox(NULL, "ERROR Accept", "socketIndication", MB_OK);
        WSACleanup();
        return 0;
    }

    //while(client != INVALID_SOCKET) {
    while(client != INVALID_SOCKET && recv(client, buf, 2, 0) != SOCKET_ERROR)
    {
        memset(&OurInfo, '\0', sizeof(OurInfo));

        // Print general scoring info *KNIP*

        } 
                   
        if(send(client, OurInfo, strlen(OurInfo), 0) == SOCKET_ERROR) break;
    }
    //}

    closesocket(client);
    closesocket(server);
    WSACleanup();
    
    serverAlive = false;
    
    //MessageBox(NULL, "Thread should close here...", "socketIndication", MB_OK);

    return 0;
}

Ik bespeur hier een zekere mate van onethische logica.


  • Bolk
  • Registratie: februari 2001
  • Niet online

Bolk

Change the equation.

Topicstarter
Ja dat zou kunnen voor het mooie inderdaad.

Ik had een bokkende internet verbinding. Ben er daarom per ongeluk eigenlijk achter gekomen. Ziggo voert hier nachtelijk nogal wat werk uit dus vandaar. De client draait hier 24/7 op een testserver en de server met de game staat in Haarlem. Vandaar de timeouts en het connectie probleem.

Maar het lijkt nu goed te werken. Nogmaals bedankt.

Offtopic: ligt het aan mij of is C++ uit z'n voegen gegroeid? Ik mis een beetje structuur maar dat kan natuurlijk ook aan mijn zwaar geringe kennis liggen. Krijg m'n hoofd er niet helemaal omheen zegmaar :P

Ik bespeur hier een zekere mate van onethische logica.


  • Bolk
  • Registratie: februari 2001
  • Niet online

Bolk

Change the equation.

Topicstarter
leuk_he schreef op dinsdag 05 oktober 2010 @ 21:54:
[...]


offtopic:
Even afgezien het feit Of C++ uit zijn voegen gegroeid is, jij gebruikt daar voor 95% C, ik zie bijna geen C++ features. Dan zou je een socket class gebruiken. Niks mis mee om C te gebruiken
Thanks, dat verklaart een hoop :)

Ik bespeur hier een zekere mate van onethische logica.

Pagina: 1


Nintendo Switch (OLED model) Apple iPhone 13 LG G1 Google Pixel 6 Call of Duty: Vanguard Samsung Galaxy S21 5G Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True

Tweakers maakt gebruik van cookies

Bij het bezoeken van het forum plaatst Tweakers alleen functionele en analytische cookies voor optimalisatie en analyse om de website-ervaring te verbeteren. Op het forum worden geen trackingcookies geplaatst. Voor het bekijken van video's en grafieken van derden vragen we je toestemming, we gebruiken daarvoor externe tooling die mogelijk cookies kunnen plaatsen.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Forum cookie-instellingen

Bekijk de onderstaande instellingen en maak je keuze. Meer informatie vind je in ons cookiebeleid.

Functionele en analytische cookies

Deze cookies helpen de website zijn functies uit te voeren en zijn verplicht. Meer details

janee

    Cookies van derden

    Deze cookies kunnen geplaatst worden door derde partijen via ingesloten content en om de gebruikerservaring van de website te verbeteren. Meer details

    janee