Detecting Client/Server Disconnect C++ Winsock

Before this is marked as a duplicate let me get this out of the way. I have checked multiple methods and questions on StackOverflow and other sites, yet it doesn't work. I assume there is something within my code preventing it from working which is why I am here. What I've tried: select() & checking for SOCKET_ERROR recv() & checking for 0 & SOCKET_ERROR send() & checking for -1

I am using Visual Studios 2017 & Winsock2 I am trying to work my code around this scenario: The client(or server) application is closed with the X Button or Alt-F4ed or TaskManagered the Client(or server) will then detect the server/client is not connected within the timeframe of instant-60seconds and then wait to reconnect. I assume the client can use the same method as the server to detect disconnect(s)

Do note my code is from around 45min-1hour of testing to find a way to make this work so it is messy and maybe even incorrect

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
94
95
96
97
98
DWORD WINAPI CliMan(LPVOID lpParam)
{
    do {
        Sleep(100); //Prevent CPU over-usage
        ds.ret = recv(ds.newsock, NULL, NULL, 0);
        ds.sret = send(ds.newsock, "-cc", sizeof("-cc"), 0);
        if (ds.ret == SOCKET_ERROR)
        {
            printf("Recv threw socket err");
            break;
        }
        else if(ds.ret == 0)
        {
            printf("Recv threw 0");
            break;
        }
        else if (ds.sret == SOCKET_ERROR)
        {
            printf("ds.sret threw -1");
        }
        else if (ds.sret == -1)
        {
            printf("ds.sret threw -1");
        }
        else {}
        //Try Select stuff now i guess.
        FD_ZERO(&ds.rset);
        FD_ZERO(&ds.sset);
        FD_SET(ds.sock, &ds.rset);
        FD_SET(ds.newsock, &ds.sset);
        ds.selret = select(0, &ds.rset, &ds.sset, NULL, NULL);
        if (ds.selret == SOCKET_ERROR)
        {
            printf("selret threw sock err");
        }
        else if (ds.selret == 0)
        {
            printf("selret threw 0");
        }
        else {}

    } while (true);
    getch();
    return 0;
}

int main()
{
    // Initialize Socket and WSA
    int ret = WSAStartup(MAKEWORD(2, 2), &ds.wsa);
    if (ret != 0)
    {
        MessageBoxA(NULL, "WSA Err", "WSA Error", MB_OK);
        return 1;
    }
    ds.sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ds.sock == INVALID_SOCKET)
    {
        MessageBoxA(NULL, "Sock() Err", "Socket() Error", MB_OK);
        return 1;
    }
    //Fill struct
    memset(&ds.server, 0, sizeof(ds.server));
    ds.server.sin_family = AF_INET;
    ds.server.sin_addr.s_addr = INADDR_ANY;
    ds.server.sin_port = htons(3939);

    //Bind Socket
    if (bind(ds.sock, (struct sockaddr*)&ds.server, sizeof(ds.server)) == SOCKET_ERROR)
    {
        MessageBoxA(NULL, "Bind() Err", "Bind() Error", MB_OK);
        return 1;
    }
    //Listen 
    if (listen(ds.sock, 1) == SOCKET_ERROR)
    {
        MessageBoxA(NULL, "Listen() Err", "Listen() Error", MB_OK);
        return 1;
    }
    SetWindowText(i.h2, L"Listening...");
    //Wait for a connection (LOOP)
    ds.newsock = SOCKET_ERROR;
    do {
        ds.newsock = accept(ds.sock, (SOCKADDR*)&ds.addr, &ds.addrlen);
    } while (ds.newsock == SOCKET_ERROR);
    ds.ip = inet_ntoa(ds.addr.sin_addr);
    SetForegroundWindow(i.hWnd);
    strcpy(ds.mboxout, "Client: ");
    strcat(ds.mboxout, ds.ip);
    MessageBoxA(NULL, ds.mboxout, "!INFO!", MB_OK);
    SetWindowText(i.h2, L"Connected");
    ShowWindow(i.h5, 1);
    boolv.clicon = 1; //Client Connected Bool.
                      //Begin Client Manager.
    i.ithreads[2] = CreateThread(NULL, NULL, CliMan, NULL, NULL, NULL);
    WaitForSingleObject(i.ithreads[2], INFINITE);
    return 0;
}
Last edited on
I have found a solution to detecting a disconnect in general but it takes around 15-20 seconds. Is there a faster way?
What is this detection good for?
In the actual visual application after breaking the do-while loop in CliMan it closes sockets and restarts the connection thread (in this case main) to await reconnection.
...

send a UDP packet every 1/2 a second or so.

while(forever)
if (nothing to read)
{
timer stuff...
if(timer too big)
reconnect()
}

....
other computer

on timer()
{
sendto()...
}


You can detect a fail way down in the subsecond range.
You should probably give it a little while (1-5 seconds, depending) before failing though. Network stuff happens, and reconnect takes a while ...

Last edited on
Topic archived. No new replies allowed.