Jump to content

  • Log In with Google      Sign In   
  • Create Account


Multithreaded server in C++ and Win32


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 password   Members   -  Reputation: 181

Like
0Likes
Like

Posted 03 April 2008 - 01:39 AM

I've been searching around for about 4 hours now about how to implement Winsock in a threaded program. I didn't find anything good at all, only a bunch of weird examples that doesn't actually work or use Winsockets. How can I structure my program so I can handle many clients at once? My code so far is good enough to handle one client. Right now it looks something like this.
	WSADATA wsaData;
	SOCKET ListenSocket;
    int iResult;

    struct addrinfo *result = NULL,
                *ptr = NULL,
                hints;

    // initiera Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
		std::cout << "WSAStartup failed: " << iResult << std::endl;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
		std::cerr << "getaddrinfo failed: " << iResult << std::endl;
        WSACleanup();
    }

	ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
		std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;
        freeaddrinfo(result);
        WSACleanup();
    }

    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
		std::cout << "bind failed: " << WSAGetLastError() << std::endl;
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
    }

    freeaddrinfo(result);

    if (listen(ListenSocket, SOMAXCONN ) == SOCKET_ERROR) {
		std::cout << "Error at bind(): " << WSAGetLastError();
        closesocket(ListenSocket);
        WSACleanup();
    }

	SOCKET ClientSocket = INVALID_SOCKET;

    // accepterar för tillfället bara en anslutning från klientsidan
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
    }

    // closesocket(ListenSocket);

    char recvbuf[DEFAULT_BUFLEN];
    int iSendResult;
    int recvbuflen = DEFAULT_BUFLEN;

	// ta emot paket tills den anslutade stänger av sin anslutning
    do {
		iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
			std::cout << "Bytes received: " << iResult << std::endl;

            // Echo the buffer back to the sender
            iSendResult = send(ClientSocket, recvbuf, iResult, 0);
            if (iSendResult == SOCKET_ERROR) {
				std::cout << "send failed: " << WSAGetLastError() << std::endl;
                closesocket(ClientSocket);
                WSACleanup();
                return 0;
            }

		std::cout << "Bytes sent: " << iSendResult << std::endl;

	} else if (iResult == 0) {
		std::cout << "Connection closing.. " << std::endl;

	} else {
		std::cout << "recv failed: " << std::endl;
        closesocket(ClientSocket);
        WSACleanup();
        return 0;
    }

    } while (iResult > 0);

    // shutdown the send half of the connection since no more data will be sent
    iResult = shutdown(ClientSocket, SD_SEND);
	if (iResult == SOCKET_ERROR) {
		std::cout << "shutdown failed: " << WSAGetLastError() << std::endl;
        closesocket(ClientSocket);
        WSACleanup();
        return 0;
    }
Thankful for help. I've been trying everything I can.

Sponsor:

#2 jochen   Members   -  Reputation: 333

Like
0Likes
Like

Posted 03 April 2008 - 01:56 AM

Hi password

I recently took a close look at boost::asio. And I have to say it's really smooth. I really like it. Also there are plenty of examples that deal with severeal standard networking scenarios. Maybe it could be a usefull for you.

Best Jochen

#3 jochen   Members   -  Reputation: 333

Like
0Likes
Like

Posted 03 April 2008 - 01:57 AM

Oh, and just in case you don't know boost, here is a direct link
http://boost.org/doc/libs/1_35_0/doc/html/boost_asio.html.

Best
Jochen

#4 password   Members   -  Reputation: 181

Like
0Likes
Like

Posted 03 April 2008 - 03:28 AM

Quote:
Original post by jochen
Hi password

I recently took a close look at boost::asio. And I have to say it's really smooth. I really like it. Also there are plenty of examples that deal with severeal standard networking scenarios. Maybe it could be a usefull for you.

Best Jochen


Nice one, that's even pure C++, I missed that from Win32 which was mostly coded in C. I'll take a look into that library.

#5 jochen   Members   -  Reputation: 333

Like
0Likes
Like

Posted 03 April 2008 - 07:25 AM

Hi password,
I hope you don't mind I reply in the public section... maybe this info is interesting for some others, too.

There is a very comprehensive "Getting Started Guide" that I recommend to work through.

Well here is how I "boost":

To keep track of changes easily I use tortoise to connect to subversion and update from time to time. In case you dont know these, simply google for "tortoise or/and subversion".

You can find a detailed description on how to setup access to subversion here.

So now that you have the boost sources and bjam on your HD, you will have to build. Simply fire up a MSVC command shell and issue bjam. Since I do this quite often I created two batch files.

JamIt32.bat for 32 bit builds:
bjam --build-dir=E:\Temp\build-boost\x86 --toolset=msvc-9.0 --build-type=complete --prefix=D:\Development\3rdParty\boost --libdir=D:\Development\3rdParty\boost\Lib\x86 --without-python --without-wave install

and JamIt64.bat for 64 bit builds:
bjam address-model=64 --build-dir=E:\Temp\build-boost\x64 --toolset=msvc-9.0 --build-type=complete --prefix=D:\Development\3rdParty\boost --libdir=D:\Development\3rdParty\boost\Lib\x64 --without-python --without-wave install

Now sit back, since this will take some time. Hint: Don't forget to use a 64bit MSVC command shell to build the 64bit version and of course you will have to adjust the paths to match your system.

Now you should have a ready to use boost version on your system.

To manage include paths, I use the Property Sheets feature of Visual Studio.
These are quite usfull, if you are tired of setting up the same include paths in any new prject over and over again. MSDN has good documentation on that: Property Sheets (C++).

You don't need to explicitely link against boost libs, because most of them are header only anyways. And the non header only libs are autolinked via pragmatas.

Well finally there is one thing expecially in case you intend to use asio:
Documentation. Building boost documentation is imho a tricky thing and therefore I prefer online documentation. However in case you don't have constant internet access, simply download a release package from time to time.

Also: Version 1.35 has just been released. But I think in a few weeks you will find a 1.35 boost msi here: boost consulting

I hope this is somehow usefull for you. In case not, simply drop me a line and I will do my best to supply more/better information.

Well finally enjoy boost::asio. Which imho makes network programming really fun.

Best
Jochen





#6 password   Members   -  Reputation: 181

Like
0Likes
Like

Posted 03 April 2008 - 10:01 AM

There was a lot of those steps I didn't understand, but i've done the following now.

1. Extracted the latest .rar of Boost into the following folder.
"C:\Program Files\boost\boost_1_35_0"

2. Downloaded bjam and opened its *build file and it did something (have no idea). Now when i'm trying to issue the commands like this one: bjam --build-dir=build-directory --toolset=toolset-name stage

It doesn't find bjam. It can only find it when I type "bjam ^".


> bjam ^
> More?
> More? --help
> 'bjam' is not a recognized command...

The same happens when I use this command.

> bjam --build-dir=build-directory --toolset=toolset-name stage
> 'bjam' is not a recognized command...


Sorry, but it feels like they intentionally made it as hard as it can be to install this library. I don't have a clue what to do, thanks for writing all that stuff up though.

Isn't it possible to just download all of the .lib files? Right now the only thing I miss are the lib files.

#7 pulpfist   Members   -  Reputation: 528

Like
0Likes
Like

Posted 03 April 2008 - 11:30 AM

You could create a thread for each incoming connection.
Here is some pseudo code (without error detection or cleanup code)


...
while(server_is_still_running)
{
// Wait for the next client to connect
clientSocket = accept(...);

// Spawn a thread to deal with the new client
CreateThread(..., ThreadFunc, (void*)clientSocket);
}

int WINAPI ThreadFunc(VOID* arg)
{
int* pClientSocket = (int*)arg;

// use send/recv here to communicate with this socket...
}




edit:
If you don't want to go with threads you should be able to deal with multiple clients by using the select call. select can be tricky to handle right but it can be used to everything from detecting new connections to dealing with existing ones in an asynchronous manner.

[Edited by - pulpfist on April 3, 2008 5:30:25 PM]

#8 phear-   Members   -  Reputation: 162

Like
0Likes
Like

Posted 03 April 2008 - 05:55 PM

Before you do anything, I suggest you learn about threading first. Learn about critical sections/mutexes/semaphores/etc. first and then incorporate winsock in to that. You need a good background in multithreading before you start messing with multithreaded servers as they are quite complex. MSDN is your best bet to look at. If you need help, you can pm me.

#9 jochen   Members   -  Reputation: 333

Like
0Likes
Like

Posted 03 April 2008 - 10:15 PM

hi password,

If u have the latest package installed extracted to C:\Program Files\boost\boost_1_35_0, do the following:

Copy bjam.exe to this directory, too.
Start a MSVC command shell.
type cd "C:\Program Files\boost\boost_1_35_0"
type (all in one line) bjam --build-dir=E:\Temp\build-boost\x86 --toolset=msvc-9.0 --build-type=complete --prefix=D:\Development\3rdParty\boost --libdir=D:\Development\3rdParty\boost\Lib\x86 --without-python --without-wave install

I hope this works for u.

Best Jochen


#10 password   Members   -  Reputation: 181

Like
0Likes
Like

Posted 04 April 2008 - 04:57 AM

Quote:
Original post by jochen
hi password,

If u have the latest package installed extracted to C:\Program Files\boost\boost_1_35_0, do the following:

Copy bjam.exe to this directory, too.
Start a MSVC command shell.
type cd "C:\Program Files\boost\boost_1_35_0"
type (all in one line) bjam --build-dir=E:\Temp\build-boost\x86 --toolset=msvc-9.0 --build-type=complete --prefix=D:\Development\3rdParty\boost --libdir=D:\Development\3rdParty\boost\Lib\x86 --without-python --without-wave install

I hope this works for u.

Best Jochen


Great, it worked now. It created a directory named boost with the following folders.


| build-boost
| x86
| boost
| bin.v2
| libs
| lots of maps here

| Lib
| x86
| lots of .lib files here


Another question (hopefully my last one). The boost directory that was created, am I supposed to add it directly into the lib/ folder of the IDE so I get: MSVC/VC++/lib/boost/...?

#11 Antheus   Members   -  Reputation: 2397

Like
0Likes
Like

Posted 04 April 2008 - 06:02 AM

Quote:
Original post by password

Another question (hopefully my last one). The boost directory that was created, am I supposed to add it directly into the lib/ folder of the IDE so I get: MSVC/VC++/lib/boost/...?


Tools/Options/Projects and Solutions/VC++ Directories

Then add the paths to "Include files" and "Library files". This will give your entire IDE access to boost.

Boost libraries use auto-linking, so no additional configuration is needed, no matter how you build your applications.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS