Right now i'm making the server part of my client/server application and I came across a winsock error that I just don't know what to do about it...
The error I get is: 10038, The descriptor is not a socket
I have 2 projects, one Activex EXE which I named it "Server Thread" and another project the Server (regular exe).
The Server has a winsock control listening for connections, when it gets a new ConnectionRequest, it makes a new "Server Thread" and passes the requestID to the thread where is another winsock that acceps the connection, that's where I get the error...
Probably I get this error because the "Server Thread" winsock is in another thread, and the requestID is valid there ?
If that's true, then how am I supposed to design my multithreading server ?
I searched the vbforums & web, and I did not find anything that helped me.
Most threads when talking about Winsock Multithreading, they are talking about winsock as a control array, but that is NOT Multithreading...
What I want is to have one winsock control in each thread... and eventually an array of the threads.
I also downloaded the CSocket from here: http://www.vbip.com/winsock-api/csoc...t-class-01.asp , First I converted the "Server Thread" project for CSocket, and I got a similar error as winsock, then also I converted the Server for CSocket, and to my surprize it does not even Listen on the port, even though it's state says it's listening...
U cannot pass the request ID to another process, which is what your activeX EXE is.
What I did in this situation, when I created a multithreading winsock server using my multithreading code, was to create an instance of my ActiveX class that would listen for a connection. When it got a connection request it connected, but then sent a message back to the parent object that it had beenb accepted. The main server component then created a new ionstance of my winsock class thingy that would then listen for incoming connection.
I was thinking about that too, but I don't really like that because there is a time gap when there is nothing listening on the socket...
I would prefer if there was one socket listening, and passing the request to the new thread...
I looked at the code in the CSocket class, and noticed that before the "ConnectionRequest" is called, the connection is already accepted !! witch is contrary to what you would expect...
I want to try to understand at least the neccessary parts of CSocket, and modify the code for my needs, i.e. to be able to accept the connection from another process.
Until then, I'm hoping someone already done this ???
I don't think it's possible. Write a quick demo with the winsock control. U can't do it with that either
Think it's something to do with how VB deligates memory...not sure though.
Anyways, this was the method I came up with if I wanted my code to run "multithreading".
I played around with this write of code for about 6 months.
Woka
PS Just remember that while your activex exe is doing stuff your main svr UI cannot communicate with it.
PS Just remember that while your activex exe is doing stuff your main svr UI cannot communicate with it.
Hi Wokawidget, I just want to make sure on something.
You can't call any sub/function while the activex exe is doing something, but it works the other way around ? I mean while the activex exe is doing something, it calls some events to the main svr to give "updates" on what it's doing ? I can do that right ? theoretically it should be ok...
Where the problem occurs is if you do something like:
VB Code:
Private Sub COmmand1_Click()
lblWoof.Caption = mobjWoof.Status
End Sub
If your activeX object is "busy" ie running some code, then you will get that evil "Switch To, Retry..." error Once your activeX has finished what it's doing then above call gets made. I hate that silly error.
Hi, CVMichael, I'm surprised that someone's already had the concerns about the problem. Good to know your tries so that I won't try pass the requestID to a new winsock thread. However, I was wondering if a control Array could do it why bother multi-threading? My concern is a control Array might NOT do it.
For instance, if another winsock instance on server side is receiving big data, could it possibly block the Zero instance, the Listening Winsock? Does that mean incoming connection request won't be directed to the Listening Winsock at that moment? But maybe not. Maybe the message loop, which the winsock control is based on, still get the connection request and wait until it get a chance to pass it over to the Zero Winsock.
If someone can clarify this question I really appreciate it. If a control array can do the job well I think I better not bother to use threading.
If a lot of data gets transfered, lets say on Index 1, and and you have another user trying to connect, the ConnectionRequest event gets fired when it finds a gap in between the transfers on Index 1.
The WORST situation is when you do processing on DataArrival and you have a DoEvents in the DataArrival sub (or it's calling subs/functions). DoEvents will allow the DataArrival event to run again when the previous instance of DataArrival did not finish processing, if you have a lot of DataArrival-s like this, your stack will overflow, and your data will be a MESS...
(I don't have any DoEvents in the DataArrival event of course)
I my situation, I am connected to a database, the processing in the DataArrival could take anywhere between aproximatelly 0.1 to 10-15 seconds, on every connection.
Every time someone makes a long report from the DB it will block ALL other clients connected, so the need for multithreading is obvious...
Hi CVMichael, based on my personal experience with Winsock Control and MultiThread in VB6, I think there are 2 issures need to be considered.
1. how to dynamically connect winsock events handlers?
2. can't pass requestID
Second one seems to be impossile. How about the first concern? Any ideas? Thanks.
1. how to dynamically connect winsock events handlers?
I'm not sure what you mean, can you explain a little ?
I attached a picture of how the multithreading model looks like (for my application). If you notice in my example there are 4 clients conected, and there are 5 threads. That is because there is always one thread that is listeing for a new connection, when a new client connects it stops listening, and it raises an event to the main Server EXE to create a new Thread that will listen for a new connection, and so on...
Originally Posted by ordnance
1. how to dynamically connect winsock events handlers?
Well, actually I'm a newbie of VB for only a couple of weeks. I am sometimes lack of ideas in how VB programmers handle a particular issue. So sorry for not giving you a clear idea.
After reading your graph, I fully understand how you are going to do. It is workable. Please ignore my questions because now I think they are not smart. Thans for your instructions.
Have you looked at my "multithreading" code?
I use this to communicate between the connections running in a seperate process and my server app.
When a connection is requested I accept the connection, and tell the server app it's been accepted (viaa my multithreading gateway code). The server then spawns another connection that listens.
Hi Wokawidget, I did not look at your code, and I don't think I will, I did it before, and I got scared You use WAY to many classes/objects/files, etc. I don't want to go through that again
I read the comments in the thread where you describe the code, and I got an idea on how you did it.
The way I did mine is like this:
Thread (ActiveX EXE):
----------------
1) A form where I put a timer, and a Winsock, both of them raise events to the thread class
2) The thread class, that raises events for ANY changes in data that Main EXE needs (i.e. Client info/status, connection status, database connection status)
Main EXE:
----------------
1) A UserControl that creates one Thread, receives it's events, stores the info, and raises/forwards events to main EXE
2) Main form, has a control array of the UserControl (This way I treat the UserControl as if it was a Thread, except I can call functions/subs from it even when the real thread is busy with something)
Also, I re-use threads (same as winsock array), when I get an event from the thread to create another thread (because current one is not listening anymore), I actually search through the UserControl array to find wich thread is not doing anything (not connected to a client), and THEN I call a funtion in that thread telling it to listen.
If all threads are busy then I create a new thread. (As I was saying same as winsock array)
Ok, first of all I must say that I am new here, and I am VERY sorry for bringing up this 1-year old thread... but I have searched long and hard for these answers, and this thread is the only hope that I have got (until I start pulling my hair out!).
Basically I am in exactly the same situation that CVMichael is, and so far I am using the method where the threads are listening for the connections individually, and not the main server app...
Wokawidget:
What I did in this situation, when I created a multithreading winsock server using my multithreading code, was to create an instance of my ActiveX class that would listen for a connection. When it got a connection request it connected, but then sent a message back to the parent object that it had been accepted. The main server component then created a new instance of my winsock class thingy that would then listen for incoming connection.
CVMichael:
I was thinking about that too, but I don't really like that because there is a time gap when there is nothing listening on the socket...
... and I couldn’t agree more with CVMichael. As I said, I am using Wokawidget's method at the moment, and when my server is under intense traffic, quite a lot of the connection requests don’t get accepted (due to the slight delay, as stated by CVMichael).
Basically I want a socket that is constantly listening for connections, and when it gets connection requests, it makes the other ActiveX EXEs accept them, but I am having all of the same problems that CVMichael is.
So...CVMichael, how did you overcome this???
(I am praying to god that you're still a member of this forum!!!)
I you look at the multithreading link in my sig this will show you how to multithread...CVMichael got scared of it...not sure why, he's quite capable of reading that code as it's not that complicated...
Just using activeX EXE's in your app does not make it multithreading. You have to add some lovely API code and custom functionality to make it true multithreading. This is what my vbGateway DLL does in the Multithreading link in my sig.
The demo project attached to the link in my sig is of a file search that just searches the PC for files. However, it could quite easily contain a winsock control, or anything else you want running in seperate threads.
B4 I wrote vbGateway dll, I used the code from my 1st attempt at vb6 multithreading, and produced a multi threading svr like CVMichael shows in his diagram above. However back then my multithreading code was a little complicated to implement easily into ppls apps.
My new vbGateway solved many many problems and made creating threads much much easier.
CV, did you see this code, or did my old code scare you? I never use too many classes/objects...the more the better in my book. sperate code off into it's own class. much easier to maintain and much more reusable....(within reason of course).
Everyone who replied to this thread is stilla ctive on VBF, as far as I am aware, so you're in luck.
(I am praying to god that you're still a member of this forum!!!)
Hi lozware,
sorry, but I did not overcome it.... I had the same problem when many clients want to connect at the same time.
Since I originally posted, I did not have the chance to work more on the project, and actually I gave up on it.
So your out of luck, because I still don't have the anser to that...
Waka
Yes, your code does scare me, mostly because of sooo many modules...
My programming style if very different than yours, so when I look at your code, I feel like pulling my hear out of my head
Well, maybe i'm exagerating a little bit, I'm sure i can understand your code if I really want to.
Hi Wokawidget,
I am new to the VB world...I am basically a java developer and this is my first attempt in VB 6. I have an issue regarding multi threading and i am hopeful that you and the rest of ppl here will be able to help me.
Problem: I need to develop an application where there are many threads which are all performing some task and each of them are writing to a different log file. I need to display the content of each of this log file in an synchronized manner in my DISPLAY module. I dont know where to start from..Can you kindly guide me what to do
Just a quick word of warning about Woka's method of multithreading:
Woka's method isn't true multithreading in the sense of you have 1 process that spawns multiple threads. Instead he implements a method that spawns multiple processes, similar to process forking under Linux.
This may be fine for what you are trying to do, but if you need to start sharing components or handles across the processes, then you will start coming across some problems. Take Winsock for example - you cannot listen for connections on 1 process, and then accept them on another.
I did post an example on how to do true multithreading in VB6, but unfortunately I got shot-down, purely for fact that Woka had been a member for longer and therefore his idea must be better. As a result I don’t really see much point in posting it again.
Nevertheless, if you are coming from a Java background then it would make a lot more sense to start learning VB.NET or even C#.NET. C#.NET is very similar to Java, and you'll find the .NET libraries to be quite feature-rich too.
You are correct in your assumption that my code spawns multiple processes.
...and yes there are limitations...just like there are with everything. But for the majority of things people need it works 100% perfectly.
The code you posted uses ActiveX EXEs, which are flawed for true communication between threads, which I explained to you in 2006...also, the threading APIS by Microsofts own admission is not supported in VB6. They are very unstable and cause more trouble than they are worth. That's why I wrote this code.
There's a link in my sig that points to my vbGateway (Multithreading (processing)) dll. Full source code and a demo project is included. The demo spawns multiple searches and displays the results in a single location.
This however is probably not the best code to dive into if you're not familiar with VB. Give me a shout if you need a hand.
Woka
Last edited by Wokawidget; Feb 1st, 2008 at 09:01 AM.
Hmm, I've just burnt some time trying to fiddle with this myself.
So far cross-process Winsocks won't fly, and I don't think you can get the multithreading action from an ActiveX EXE that creates objects from itself. You'd need to have a host application EXE that creates objects out of an ActiveX EXE, including a listener to have to Winsock in listening state and it would need to hand off to the worker objects to accept incoming connections... nasty.
It seems like it might be easier to keep all of the Winsocks in the host application, but delegate per-client work requests to mulithreaded objects created out of an ActiveX EXE. Lots of marshaling required though.
I don't see the need to have each connection in a separate thread. You can still handle each client in separate threads, but keep the connections in one thread.
Processing for each client can be broken up into subs which can be executed in separate threads.
I don't see what you would gain on having the actual connections on separate threads.
The main cost of having the connection separate from the worker threads is marshaling the data cross-process. In the simple case of an EXE calling into a multithreaded ActiveX EXE you have two processes, the second of which has the multiple threads.
If your connections are managed in the parent process you have move data back and forth between there and the process with the threads. This is quite expensive compared to a in-process method call. If you're moving lots of data (like file transfers) this may add up to a point where you lose any advantage from multithreading.
The sad part of these multithreading efforts is that even if you get it to work the benefits may be minimal. Thread affinity may mean all of the ActiveX EXE's threads run in the same processor anyway, even on a quad-core machine.
DigiRev, what do you mean by having the actual connections on separate threads? A network connection under windows is simply a socket handle, and it's owned by a process, not a thread. Are you refering to instances of winsock objects or what?
DigiRev, what do you mean by having the actual connections on separate threads? A network connection under windows is simply a socket handle, and it's owned by a process, not a thread. Are you refering to instances of winsock objects or what?
It seems like he wants to accept each client connection on a separate thread (passing the RequestID to another Winsock running in a separate thread).
I was just saying I don't see the point of that. What's important is that all processing for each client is done in a separate thread (so processing for one client doesn't make another one wait).
I did an Application for optics shop and the problem is to alot of one employee should record in this program, Can anyone help me to find a solution to share the database?. Knowing that i use VB6 & Access
I am crying "Uncle" on this. I have tried to make a multithreaded VB6 chat server using the Winsock control. It works 99.9% (in other words, it doesn't work).
It multithreads beautifully, with everything in a single process. Something people seem to like to think "can't be done" in VB6.
Symptoms
Clients can connect, get a server thread of their own, and get a response from the server. Then it falls over.
The client gets a Close event almost immediately, which it of course shouldn't unless I have some bizarre error in the client. However the client is almost unmodified from a basic client I have successfully used many times with a regular single-threaded server.
Oddly, the server Winsock controls still seem to think they are connected!
I've added code to display the State after this has happened, and sure enough it comes back as 7 (sckConnected). With some playing around I was on occasion getting an error in the worker threads' Winsock controls:
sckNotSocket 10038 The descriptor is not a socket
Guesses
I have come to the conclusion that either (a.) I have some bug I just can't see, or (b.) you can't Accept a requestID across threads much more reliably than processes!
Remember though, the server seems to successfully get a "greeting" message back to the clients after the Accept is done!!!
My guess is that the Accept actually works, but something on the order of a window message needs to come back to the listening socket to let it know the Accept actually happened (???). I tried Spy++ on the worker Form though and didn't see anything likely there in terms of messages.
Try It
To play with this, you need to compile both the server and the client, though the client can run from the IDE. Not the server though!
Also be sure to read the readme.txt for info on unregistering the server before each compile. This helps avoid registry clutter from creating new classIDs each compile (project has no compatibility).
Don't be afraid to use Task Manager to monitor the thread count of the server. As each client connects it should go up.
I am almost +ve you cannot pass requestIDs across threads. I have ran into that issue many times.
The way I did it was to have a thread already listening. When that thread picks up the connection it raises an event to the parent to spawn a new listening thread.
Yes, I'm aware of that solution (wasn't it discussed above here or in another thread of conversation at this site?). It is one way around it for sure, though it has the problem of rejecting connections now and then because of the way it "hands things off" with no listerner for a brief time.
They can't be passed between processes for sure. I was hoping "between threads" might be possible.
Actually it turns out that it is possible, as my demo above illustrates. The problem is, as soon as the Winsock control listener's ConnectionRequest event handler (on the main thread) exits... the established TCP connection is reset/disconnected.
We can see this because when the worker thread calls the Accept method it sends out a greeting string right away that the client actually receives. Then just as quickly the client sees the connection Close. Odder still though, the worker thread Winsock control has its State = sckConnected yet!
Doing netstat -a from a command prompt shows such connections to be in TIME_WAIT state, suggesting they were established but are in the process of being closed.
My conclusion is that this is not an issue with using Winsock sockets between threads of the same process, but an issue that the VB6 Winsock control that wraps the socket has. I.e. I have somehow broken a communication path between the Accept-ing control and the Listen-ing control.
The listener "thinks" that the ConnectionRequest event handler has rejected the connection by exiting without calling Accept.
The "path" that comes to mind immediately might be a window message that the Accept control issues, which does not get back to the Listen control on the main thread/Form. If this were true, the worker Form might be subclassed, pick up the mystery message, and send it to the main (UI) Form with the Listen control via SendMessage.
But it might not be a window message that's missing here at all. Maybe something else is going on.
Last edited by dilettante; Feb 26th, 2009 at 08:46 AM.
I haven't read the complete thread, but this might be an idea that hasn't been used:
Create a thread and let it listen. When it gets a connection, let the main app launch a new thread.
What's the whole point of passing the RequestID to another control?
Well the new thread starts listening again.
There is no point in having the main app listening while the thread itself can too.
So when a thread accepts a connection it gives signal to the main app saying it's busy, so the main app launches another thread and you always have a thread open to listen.
You can see this as a callcenter where the personnel is so to speak the threads and the employment manager the main application.
If the whole point's that you're worried about not being able to get connection at the same port, you should do some research on the BIND function.
Last edited by TheBigB; Mar 7th, 2009 at 04:41 AM.