This Makes No Sense! - Winsock

Well actually I'm sure it will make sense to somebody:

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

//Server Side

#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <process.h>
#include <Table.h>

using namespace std;

const int iReqWinsockVer = 2;   // Minimum winsock version required
const int DEFAULT_PORT = 4444;

WSADATA wsaData;
SOCKET serverSocket;

int main()
{

    if (WSAStartup(MAKEWORD(iReqWinsockVer,0), &wsaData)==0)
    {
        // Check if major version is at least iReqWinsockVer
        if (!(LOBYTE(wsaData.wVersion) >= iReqWinsockVer))
        {
            cout << "Couldn't get WINSOCK version 2 or greater";
        }

        unsigned int* threadID;
        _beginthreadex(NULL, 0, runServer, NULL, 0, threadID);

        cout << "Enter X To Stop Server: ";

        char userInput;

        while(running)
        {

            cin >> userInput;

            if(userInput == 'X')
            {
                cout << "Stopping Server" << endl;
                shutdown(serverSocket,1);
                running = false;
            }

        }

        cout << "Last Error: " << WSAGetLastError() << endl;

        if (WSACleanup()!=0)
        {
            cout << "Cleanup Failed";
        }

    }
    else
    {
        cout << "Startup Failed";
    }

    return 0;

}


Without the call to WSAGetLastError() the program will run, it crashes with an illegal memory access error on return 0 - so it gets all the way to the end lol

With the WSAGetLastError() call, the program crashed at the very start, doesn't even output: Enter X To Stop Server. Crashes with the illegal memory access stuff. This just doesn't make sense to me lol how could this line crash the program if we don't even get to it?

If I don't run the thread - this is where the socket gets set up and accepts connections - then I don't have either of the above problems. I'll put what I believe to be the relevent part of the thread below - I've determined that the error still occurs with this bit (just commented out the other stuff):

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

unsigned __stdcall runServer(void * param)
{

    SOCKET clientSocket;

    sockaddr_in sockAddr = {0};

    cout << "Creating socket... ";
    if ((serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
    {
        cout << "Error creating server socket";
        return 0;
    }
    cout << "created." << endl;

    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons((u_short)DEFAULT_PORT);
    sockAddr.sin_addr.S_un.S_addr = INADDR_ANY;

    if (bind(serverSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr))!=0)
    {
        cout << "Could not bind socket." << endl;
        return 0;
    }
    cout << "Bound." << endl;

    // Put socket in listening mode
    cout << "Putting socket in listening mode... ";
    if (listen(serverSocket, SOMAXCONN)!=0)
    {
        cout << "could not put socket in listening mode.";
        return 0;
    }
    cout << "done." << endl;

    //Need to add a table to the vector
    Table newTable;
    tables.push_back(newTable);

    while(running)
    {
       // Error still occurs without this stuff!
    }

    if (serverSocket!=INVALID_SOCKET)
    {
        closesocket(serverSocket);
    }

    cout << "We gona return 1" << endl;

    return 1;

}


I'm really stuck, any help would be greatly appreciated!

Nick :)



Last edited on
I don't have a Windows compiler available at the moment, but I doubt your first example would even compile: no includes, iReqWinsockVer and wsaData are not declared, etc...

Please fix that and repost so that we can help you.
Ok I updated the code.
Last edited on
1
2
        unsigned int* threadID;
        _beginthreadex(NULL, 0, runServer, NULL, 0, threadID);

should be:
1
2
        unsigned int threadID;
        _beginthreadex(NULL, 0, runServer, NULL, 0, &threadID);


Use SD_SEND rather than 1 in shutdown.

The main thread should wait for the worker thread to complete before terminating.
Hmmm weird, I made those changes and now it is doing what it was doing before. In the worker thread while loop the serverSocket accepts new connections. When I started using shutdown that appeared to cancel the blocking call and let the worker thread exit the loop. Now it is stuck at accept again. How can I get past the blocking accept call?

Thanks, Nick
Try to use closesocket() instead of shutdown().

And lines 44 and 45 should be swapped to avoid a race condition I think.
Last edited on
Ok I'm stumped lol can you try run this and tell me what you can make of it?

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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

//Server Side

#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <process.h>

using namespace std;

const int iReqWinsockVer = 2;   // Minimum winsock version required
const int DEFAULT_PORT = 4444;

WSADATA wsaData;
SOCKET serverSocket;

unsigned __stdcall runServer(void * param);

bool running = true;
bool serverThreadFinnished = false;

vector<Table> tables;

int main()
{

    if (WSAStartup(MAKEWORD(iReqWinsockVer,0), &wsaData)==0)
    {
        // Check if major version is at least iReqWinsockVer
        if (!(LOBYTE(wsaData.wVersion) >= iReqWinsockVer))
        {
            cout << "Couldn't get WINSOCK version 2 or greater";
        }

        unsigned int threadID;
        _beginthreadex(NULL, 0, runServer, NULL, 0, &threadID);

        cout << "Enter X To Stop Server: ";

        char userInput;

        while(running)
        {

            cin >> userInput;

            if(userInput == 'X')
            {
                cout << "Stopping Server" << endl;
                running = false;
                closesocket(serverSocket);
            }

        }

        while(serverThreadFinnished == false)
        {
            //Wait for worker thread to finnish
        }


        cout << "Last Error: " << WSAGetLastError() << endl;

        if (WSACleanup()!=0)
        {
            cout << "Cleanup Failed";
        }

    }
    else
    {
        cout << "Startup Failed";
    }

    return 0;

}

unsigned __stdcall runServer(void * param)
{

    SOCKET clientSocket;

    sockaddr_in sockAddr = {0};

    cout << "Creating socket... ";
    if ((serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
    {
        cout << "Error creating server socket";
        return 0;
    }
    cout << "created." << endl;

    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons((u_short)DEFAULT_PORT);
    sockAddr.sin_addr.S_un.S_addr = INADDR_ANY;

    if (bind(serverSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr))!=0)
    {
        cout << "Could not bind socket." << endl;
        return 0;
    }
    cout << "Bound." << endl;

    // Put socket in listening mode
    cout << "Putting socket in listening mode... ";
    if (listen(serverSocket, SOMAXCONN)!=0)
    {
        cout << "could not put socket in listening mode.";
        return 0;
    }
    cout << "done." << endl;

    while(running)
    {

        sockaddr_in clientSockAddr;
        int clientSockSize = sizeof(clientSockAddr);

        // Accept connection:
        clientSocket = accept(serverSocket, reinterpret_cast<sockaddr*>(&clientSockAddr), &clientSockSize);

        cout << "Get past here!" << endl;

        bool playerAdded = false;

    }

    serverThreadFinnished = true;

    return 1;

}




I'm still getting the windows error message pop up. How can I wait for the thread to terminate? I tried WaitForSingleObject(&threadID, INFINITE) but that didn't work...

Sorry for the large code paste, usually I do my best to keep it as small as possible but I'm really lost with this.

As always any help will be appreciated,

Nick!

_beginthread returns the thread handle, the thread id is not its handle.

e.g.
1
2
3
4
        unsigned int threadID;
        HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, runServer, NULL, 0, &threadID);
        //...
        WaitForSingleObject(hThread, dwTimeout);

Thanks kbw :) Everything works well now lol that was pretty stupid of me!

Also thanks to everyone else who replied!

Nick
Remember to close the handle when you're done.
Topic archived. No new replies allowed.