Login  
Search All Forums
Dart Home | PowerTCP WebServer for ActiveX | Custom Development Reply | PowerTCP WebServer for ActiveX Topics | Forums   
AuthorForum: PowerTCP WebServer for ActiveX
Topic: Multithreaded WebServer in VB6
PaulParkhurst
pparkhurst@c-cor.com

From: Beaverton, OR USA
Posts: 8
Member Since: 11/23/07
posted November 23, 2007 7:35 AM

I am trying to use the WebServer control in a multithreaded environment. I've created a VB6 ActiveX EXE project set for "thread per object". I have the WebServer instantiated on the main thread. Each time I get a POST event (this is a custom SOAP server), I instantiate a handler on a new thread, set Response.Delay = True, pass Response to the new thread, and exit. The thread sets a timer and returns immediately.

Everything actually works fine. The thread does its thing when the timer goes off, calls back to the main thread, responds to the caller (using Response.Send), and goes away as it should. The problem is this... no matter how many simultaneous web hits I make to the server, it never has more than 2 threads active at any one time. It doesn't matter if I have 5 pending hits or 25, only 2 worker threads are ever created. This is telling me that the WebServer isn't handling more than 2 simultaneous web hits, or at least isn't raising the POST event for more than 2 connections at a time.

I checked to see if there was some sort of "max connections" property on the WebServer, but didn't find any. I'm doing everything correctly (as far as I know) according to the documentation for using the WebServer in a multithreaded environment. Is there a limit to the number of simultaneous hits the WebServer can be servicing at any one time? Is there a trick I'm missing? Is there possible contention using the Response object in multiple threads (I know different instances are used for each POST event, but I'm guessing they're all created on the same WebServer thread)? I only make 3 calls to Response in the worker threads themselves: Response.Body.Write, Response.Status, and Response.Send. That's it. I can't see how that could possibly tax the WebServer thread.

Any help or information anyone could give would be appreciated.

Paul
Arjun

From: Rome, NY, USA
Posts: 137
Member Since: 09/17/07
posted November 23, 2007 1:14 PM

Hello Paul,

The following is the information about Multithreading:
Multi-threaded Use
Like most controls, PowerTCP Server Controls are apartment model threaded. All events fire on the same thread that created the control. Consequently, any processing that takes place within the body of an event, such as the Get event, normally block processing of all other events fired on the same thread. Thus, any lengthy database query made within the body of an event could negatively impact other connections, because those additional connections would not be serviced until the first was completed. Consequently, the design is a single control with asynchronous support.
From within any HTTP event, a new thread can be spawned using MTS or some other mechanism that ultimately responds to the event, while the user thread returns to the WebServer Control to process other requests. The mechanism is accomplished by setting Response.Delay to True, creating an object on a new thread, passing it a reference to the Response Object, and calling Response.Send once the lengthy operation is complete.
Although this approach is less "pure" than having a dedicated thread for each TCP connection, it is useful for servers that anticipate high loading, while maintaining simplicity and speed of operation for developers anticipating medium to light loads.
Application Partitioning Applies To WebServer Control Only
Besides the single application, multi-threaded approach discussed above, the compiled nature of your web application allows you to partition your application into multiple tasks, each listening on unique ports and operating independent of other applications. For example, suppose you have a number-crunching task that is not often exercised, but when it is it needs to be on it's own thread. You can write a second web application for this task, have it listen on port 81, and link to it whenever it needs to be run. Your main web application never notices because your second application is running in its own task space.

For the number of connections, please note that there is no limit for the number of connections from our side. However the OS, system resources can limit the number of connections.

Also I would request you to please make sure that you have the latest version of the control installed. You ay check the version installed by running the DartNostics utility provided with the control. The present latest version is 1.8.3.3. Incase you do not have the latest version please let me know.

Also I would request you to please try with the samples provided and check if the problem persists. You may find the samples at the following location:
C:\Program Files\PowerTCP\WebServer for ActiveX\Samples\

I have tried by running the sample and then accessing it from 6 different instances and it worked as expected.

I hope this helps.

Have a great day.

Regards,
Arjun
PaulParkhurst
pparkhurst@c-cor.com

From: Beaverton, OR USA
Posts: 8
Member Since: 11/23/07
posted November 24, 2007 5:14 AM

Thanks for the reply, Arjun. As it turns out, the WebServer is actually working correctly. I did have some bizzare issues with the POST event being reentrant (had to jump through some hoops with that problem; you may want to mention the possibility of reentrancy in WebServer events in the help file), but I believe I have it working now.

As it turns out, the problem was with a multithreaded client I created using the Dart Http control. I'm doing basically the same thing with this application, only in reverse. I receive a number of messages I want to send to my SOAP server, create a handler object on separate threads for each one, start the threads (with a timer of course), and just let the thread deal with the connection. The thread will then instantiate an Http control and attempt to do a Post method call to my server.

Here's the weird thing: the first two threads I start in this way actually make the connection to the server when they call the Http.Post method. The remaining threads threads never actually perform a connect when Http.Post is called. The call blocks as it should, and at the end of the timeout I get the standard 9060 error ("Caused when Get, Head, Post, or Put methods are used..." blah blah), but the connection is never attempted (the listener on the other side never registers the connection attempt).

Another odd aspect of this problem: I create multiple threads to make an HTTP connection, as I explained earlier. The first two, again, actually attempt to make a connection while the rest just sit there at Http.Post. But... once one of the first two connections complete and are finished, THEN one of the remaining threads actually attempts the connect!!! This goes on, with only two connections being requested at any one time, until all the threads either make a connection or time out.

I tested this same scenario using a standard WinSock connection rather than using the Http control and I get all the connects to my server. But when using the Http control, only 2 connections are ever active at one time. Once one finishes, then it seems like another one of the currently waiting Post methods makes a connection. Each Http control is being instantiated on a different thread, and I am using the blocking model for the Post calls (I think my timeout is 15 seconds).

Is there some limit to the number of total connections that are allowed by all Http controls in each process at any one time? That's what it looks like is happening. Again, if I try multiple WinSock connections, my server sees all connects. If I use multiple Http controls (on different threads, using the blocking model), only two connects are attempted at any one time.

I have not attempted to use non-blocking for the Http controls as that would greatly complicate my application. SOAP is a pretty direct request-response format, so non-blocking is unneeded. In fact, the main reason I'm using multiple threads is specifically so I can block and not effect other connection attempts.

Any help would be appreciated. Thanks!

Paul
Arjun

From: Rome, NY, USA
Posts: 137
Member Since: 09/17/07
posted November 27, 2007 8:45 AM

Hello Paul,

With regards to the query I would suggest you to use our WebASP control instead of Web Tool (HTTP).
You may download the trial version of WebASP which is a part of Web Enterprise toolkit from the link below:
http://www.dart.com/ptwbe.aspx

The reason for the same is that our Web tool uses the wininet and Microsoft does not recommend using wininet in multithreaded applications.
The following article describes the same:
http://support.microsoft.com/kb/183110

I hope this helps.

Have a great day.

Regards,
Arjun
PaulParkhurst
pparkhurst@c-cor.com

From: Beaverton, OR USA
Posts: 8
Member Since: 11/23/07
posted November 27, 2007 4:45 PM

Well, at least I know that I'm not completely nuts and that I did everything the way I was supposed to :-) Who would have thought they'd knee-cap their own protocol like that? Thanks again, Arjun. I think I have enough info to get everything working.

Paul
Arjun

From: Rome, NY, USA
Posts: 137
Member Since: 09/17/07
posted November 28, 2007 8:34 AM

Hello Paul,
 
Thank you for writing back and letting us know that the response was helpful.
 
Let me know if you have further questions.
Have a great day.
 
Regards,
Arjun
Reply | PowerTCP WebServer for ActiveX Topics | Forums   
This site is powered by PowerTCP WebServer Tool PowerTCP WebServer for ActiveX